一 .cookie应用
1. cookie简介
在程序中,会话跟踪是很重要的事情。理论上,一个用户的所有请求操作都应该属于同一个会话,而另一个用户的所有请求操作则应该属于另一个会话,
二者不能混淆. 而Web应用程序是使用HTTP协议传输数据的。HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。
这就意味着服务器无法从连接上跟踪会话。要跟踪该会话,必须引入一种机制。
Cookie就是这样的一种机制。它可以弥补HTTP协议无状态的不足。在Session出现之前,基本上所有的网站都采用Cookie来跟踪会话。
关于cookie,需要记住几点: - 1.cookie是保存在用户浏览器的已加密的键值对 - 2.可以被主动清除(浏览器界面、前端、后台) - 3.可以被"伪造" - 4.处于隐私保护的目的,禁止跨域共享:即www.googole.com和www.baidu.com各自的cookie不可被共享,因为域名对应的谷歌公司和百度公司服务器是不同的
设置cookie def coo(request): if request.method=="POST": print(request.COOKIES) name=request.POST.get("usre") pwd=request.POST.get("pwd") if name=="aaaa" and pwd=="123": ret=redirect("/myapp/index") ret.set_cookie("lover","good") # 设置 set_cookie return ret return render(request,"html_app/05cookie.html")
获取cookie def index(request): if request.COOKIES.get("lover",None)=="good": name="aaaa" return render(request,"html_app/06index.html",{"aa":name}) else: return redirect("/myapp/cookie/")
cookie技术 带有过期时间
def coo(request): if request.method=="POST": print(request.COOKIES) name=request.POST.get("usre") pwd=request.POST.get("pwd") if name=="aaaa" and pwd=="123": ret=redirect("/myapp/index") ret.set_cookie("lover","good") # 设置 set_cookie # ret.set_cookie("username",{"11":"22"},max_age=10) #设置 set_cookie 和过期时间 ret.set_cookie("username",{"11":"22"},max_age=10,expires=datetime.datetime.utcnow()+datetime.timedelta(days=3)) #设置 set_cookie 和过期时间 return ret return render(request,"html_app/05cookie.html") def index(request): if request.COOKIES.get("username",None) name=request.COOKIES.get("username",None) return render(request,"html_app/06index.html",{"aa":name}) else: return redirect("/myapp/cookie/")
# views.py def login(request): # 登陆页面 if request.mothod == 'POST': name = request.POST.get('user') pwd = request.POST.get('pwd') if name == 'yuan' and pwd == '123': ret = redirect('/index/') ret.set_cookie('key','value') # 登陆成功后,给cookie赋一组键值对 # ret.set_cookie('username','yuan',max_age=10,expires=datetime.datetime.utcnow()+datetime.timedelta(days=3)) # max_age设置cookie过期时间为10秒,expires设置cookie过期时间为3天(针对不同浏览器,需要同时设置这两个值,并设置为一样) return ret def index(request): # if request.COOKIES.get('key',None): # 判断用户是否有cookie设置的key if request.COOKIES.get('key',None)=='value': # 获取cookie的值,判断key是否为value,None代表取不到时以None代替,这样不报错 return render(request,'index.html',locals()) else: return redirect('/login/')
游览器查看cookie的方法:这里的cookie可以通过游览器的“审查元素”-> "network" -> "Cookies" 看到 request.COOKIES:包含用户发来的所有数据,这个COOKIES就是一个字典,获取方法有以下2种 获取cookis,获取用户发来请求中的cookies request.COOKIES['username111']
request.COOKIES.get('username111') 设置cookies,服务器端返回给客户端,并写入cookies response = render(request,'index.html') response = redirect('/index/')
# 设置cookie,关闭游览器自动失效 response.set_cookie('key','value') return response
# 设置cookies超过10秒失效,写法 response.set_cookie('key','value',max_age=10)
# 从登录10秒后失效,写法 current_time = datetime.datetime.utcnow() current_data = current_time + datetime.timedelta(seconds=10) response.set_cookie('key','value',expires=current_data)
rep.set_cookie(key,value,...) rep.set_signed_cookie(key,value,salt='加密盐',...) 参数: key, 键 value='', 值 max_age=None, 超时时间 expires=None, 超时时间(IE requires expires, so set it if hasn't been already.) path='/', Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问 domain=None, Cookie生效的域名 secure=False, https传输 httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
cookie 将字符串进行salt加解密,写法如下: obj = HttpResponse('s') obj.set_signed_cookie('username','jack',salt='adfadf') # 通过salt进行加密 request.get_signed_cookie('username',salt='adfadf') # 通过原来的salt进行解密 注意:获取cookies写法:request.COOKIES.get('名称') 设置cookies写法:response.set_cookie('key','value')
实例:FBV实现一个帐号登录后,保持10秒,并使用装饰器检查每个URL都为帐号登录状态
def auth(func): ''' 装饰器,检查当前游览器cookies里logname是否存在已登录的帐号,如果存在,则继续执行下面的函数,返回计划进入的url''' def inner(request,*args,**kwargs): v = request.COOKIES.get('logname') if not v: return redirect('/') return func(request,*args,**kwargs) return inner def login(request): '''登录url ''' if request.method == 'GET': return render(request,'login.html') def index(request): if request.method == 'GET': '''get模式,获取cookies的logname帐号名,如果为空则返回登录页面 ''' u = request.COOKIES.get('logname') if not u: return redirect('/') if request.COOKIES['logname'] == 'admin': alluser = models.UserName.objects.exclude(uname='admin') else: # loguser = request.session['username'] loguser = request.COOKIES['logname'] alluser = models.UserName.objects.filter(uname=loguser) return render(request, 'index.html', {'u_list': alluser} if request.method == 'POST': '''帐号登录验证 ''' logname = request.POST.get('logname',None) logpwd = request.POST.get('logpwd',None) if models.UserName.objects.filter(uname=logname): if models.UserName.objects.filter(uname=logname,upwd=logpwd): # 登录验证成功,重写cookie的登录帐号,延时10秒 response = HttpResponse('ok') response.set_cookie('logname',logname,max_age=10) return response else: return HttpResponse('pwderr') else: return HttpResponse('nmerr') @auth # 装饰器,在访问url为account时候,验证帐号是否为登录状态 def account(request): if request.method == 'GET': return render(request,'account.html')
CBV通过装饰器实现用户登录认证
from django import views from django.utils.decorators import method_decorator @method_decorator(auth,name='dispatch') class Order(views.View): def get(self,request): v = request.COOKIES.get('logname') return render(request,'index.html',{'current_user':v}) def post(self,request): v = request.COOKIES.get('logname') return render(request,'index.html',{'current_user':v
2. cookie装饰器版
def check_login(func): @wraps(func) def inner(request, *args, **kwargs): next_url = request.get_full_path() if request.get_signed_cookie("login", salt="SSS", default=None) == "yes": # 已经登录的用户... return func(request, *args, **kwargs) else: # 没有登录的用户,跳转刚到登录页面 return redirect("/login/?next={}".format(next_url)) return inner def login(request): if request.method == "POST": username = request.POST.get("username") passwd = request.POST.get("password") if username == "xxx" and passwd == "dashabi": next_url = request.GET.get("next") if next_url and next_url != "/logout/": response = redirect(next_url) else: response = redirect("/class_list/") response.set_signed_cookie("login", "yes", salt="SSS") return response return render(request, "login.html")