前戏
我们在访问一些网站的时候,如果没有登录就会跳转到登录页面,如果是登录了,才会让我们访问,那服务器是怎么知道我们有没有登录呢?这就涉及到了Cookie,大家都知道HTTP的特点,无状态。也就是浏览器发送到服务器的每个请求都是没有关系的。这时候就要给服务器设置一个Cookie,下次浏览器请求的时候,携带这个Cookie,如果有携带,那服务器就认为是登录的,如果没有携带或错误,那浏览器就跳转到登录页面。
什么是Cookie呢?
Cookie是指一小段信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对。Cookie的工作原理是由服务器产生内容,浏览器收到请求后保存在本地,当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie判断当前用户是哪个了
Cookie初识
login.html
我们写三个视图函数,login,home和index
from django.shortcuts import render,redirect,HttpResponse from appTest01 import models # Create your views here. def login(request): if request.method == 'POST': user = request.POST.get('username') password = request.POST.get('pwd') if models.Person.objects.filter(name=user, pwd= password): return redirect('/index/') return render(request,'login.html') def index(request): return HttpResponse('index') def home(request): return HttpResponse('home')
上面这样的写法,我们可以直接通过路径访问对应的页面,不需要登录,当然不符合我们的需求,那我们给加上Cookie
from django.shortcuts import render,redirect,HttpResponse from appTest01 import models # Create your views here. def login(request): if request.method == 'POST': user = request.POST.get('username') password = request.POST.get('pwd') if models.Person.objects.filter(name=user, pwd= password): ret = redirect('/index/') ret.set_cookie('is_login','yes') return ret return render(request,'login.html') def index(request): print(request.COOKIES,type(request.COOKIES)) 查看cookie return HttpResponse('index') def home(request): return HttpResponse('home')
我们使用set_cookie()来设置Cookie,然后我们输入账号密码去登录,查看cookie
我们可以使用 request.COOKIES来查看cookie,
request.COOKIES,type(request.COOKIES)
结果:
{'csrftoken': 'pB5vZxQOwWnvNyw13S0ImpbInxOpnIV0BsAcE31hCHLOP3EIMM8veLpxIlcRBYIg', 'is_login': 'yes'} <class 'dict'>
既然它是一个字典类型的,我们就可以拿到cookie,然后在进行一个判断,在来改写视图函数
from django.shortcuts import render,redirect,HttpResponse from appTest01 import models # Create your views here. def login(request): if request.method == 'POST': user = request.POST.get('username') password = request.POST.get('pwd') if models.Person.objects.filter(name=user, pwd = password): ret = redirect('/index/') ret.set_cookie('is_login','yes') return ret return render(request,'login.html') def index(request): if request.COOKIES.get('is_login') == 'yes': # 获取我们设置的Cookie return HttpResponse('index') return redirect('/login/') def home(request): if request.COOKIES.get('is_login') == 'yes': return HttpResponse('home') return redirect('/login/')
上面代码我们就实现了我们的需求,如果登录成功,可以访问index和home页面,如果没有登录,则返回login页面,那试想一下,以后我们的项目页面有几百个,难道要给每个页面都要写判断吗?这样肯定是不行的,我们可以用装饰器来实现这种需求,代码如下
from django.shortcuts import render, redirect, HttpResponse from appTest01 import models # Create your views here. def login_cookie(f): def inner(request, *args, **kwargs): if request.COOKIES.get('is_login') == 'yes': # 获取我们设置的Cookie,如果通过,执行被装饰的函数 res = f(request, *args, **kwargs) return res return redirect('/login/') return inner def login(request): if request.method == 'POST': user = request.POST.get('username') password = request.POST.get('pwd') if models.Person.objects.filter(name=user, pwd=password): ret = redirect('/index/') ret.set_cookie('is_login', 'yes') return ret return render(request, 'login.html') @login_cookie def index(request): return HttpResponse('index') @login_cookie def home(request): return HttpResponse('home')
但是这样又有个问题,如果我们没有登录访问home页面,它会跳转到登录页面,我们正确登录之后返回到了index页面,这肯定不是我们需要的效果,因为我们在login函数里已经写死了,登录成功之后返回的是index页面,我们来看下京东没登录时点击“我的京东”是怎样处理的
我们可以看到,京东在登录页面后面加了个参数,然后登录成功之后,直接跳转到后面的那个参数页面了,那我们在来修改我们的代码
from django.shortcuts import render, redirect, HttpResponse from appTest01 import models # Create your views here. def login_cookie(f): def inner(request, *args, **kwargs): current_url = request.path_info # 获取地址中?后面的参数 print('current_url为:', current_url) if request.COOKIES.get('is_login') == 'yes': res = f(request, *args, **kwargs) return res return redirect('/login/?returnurl={}'.format(current_url)) # 拼接url路径 return inner def login(request): if request.method == 'POST': user = request.POST.get('username') password = request.POST.get('pwd') if models.Person.objects.filter(name=user, pwd=password): url_parameter = request.GET.get('returnurl') # 获取当前路径里的returnurl参数 ret = redirect(url_parameter) # 返回到returnurl页面 ret.set_cookie('is_login', 'yes') return ret return render(request, 'login.html') @login_cookie def index(request): return HttpResponse('index') @login_cookie def home(request): return HttpResponse('home')
结果:
如果你在未登录状态下访问home页面,current_url就为/home/ 如果你在未登录状态下访问index页面,current_url就为/index/
那么问题又来了,如果我们直接访问login页面,登录成功则会报错,这是因为当前的 url_parameter 参数为空,只需要修改login函数里的东西就可以了
def login(request): if request.method == 'POST': user = request.POST.get('username') password = request.POST.get('pwd') if models.Person.objects.filter(name=user, pwd=password): url_parameter = request.GET.get('returnurl') # 获取当前路径里的returnurl参数 if url_parameter: # 如果有值 ret = redirect(url_parameter) # 返回到returnurl页面 else: # 如果为空 ret = redirect('/home/') ret.set_cookie('is_login', 'yes') return ret return render(request, 'login.html')
设置和获取Cookie
在上面的例子中,我们是使用 set_cookie()来进行设置Cookie,还有另一种方式
rep = HttpResponse(...) rep = render(request, ...) rep.set_cookie(key,value,...) rep.set_signed_cookie(key,value,salt='加密盐',...)
获取Cookie就不能使用request.COOKIES[’key‘]或者request.COOKIES.get('key')的方法获取了,要使用如下的方法获取
request.get_signed_cookie('key', default=RAISE_ERROR, salt='', max_age=None)
get_signed_cookie方法的参数:
- default: 默认值
- salt: 加密盐
- max_age: 后台控制过期时间
删除Cookie
删除Cookie使用delete_cookie('key')
def loginout(request): res = redirect('/login/') res.delete_cookie('is_login') # 删除我们设置的is_login的cookie return res
Cookie的其他参数
- key,键
- value='' 值
- max_age=xx 超时时间,xx为一个int型的,单位为秒,如xx=60,则cookie的有效期为60秒
- path='/', Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问
- domain=None, Cookie生效的域名
- secure=False, https传输
- httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)