Day21-Cookie
Posted momo8238
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Day21-Cookie相关的知识,希望对你有一定的参考价值。
1. Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。例如在某个网站上保存了用户名和密码,3个月内免登陆。如果你换台电脑或者浏览器的话,则需要重新登录。就此说明cookie是保存在客户端浏览器上的一个文件。
2.实例---基于cookie实现用户信息验证
当用户名和密码都正确的时候,才跳转到index页面。否则就停留在login.html页面。
2.1 在setting中注释掉下面一句,防止报错
2.2 在urls.py中写路由对应关系
2.3 views.py写后端
dic
=
user_info.get(u)
#如果获取到了,表明用户是存在的。
from django.shortcuts import render,HttpResponse,redirect from django.urls import reverse # Create your views here. user_info={ \'dachengzi\':{\'pwd\':"123123"}, \'kanbazi\':{\'pwd\':"kkkkkkk"}, } def login(request): if request.method==\'GET\': return render(request,\'login.html\') if request.method == \'POST\': u=request.POST.get(\'username\') p=request.POST.get(\'pwd\') dic=user_info.get(u) if not dic: return render(request,\'login.html\') if dic[\'pwd\']==p: res=redirect(\'/index/\') res.set_cookie(\'username111\',u) return res else: return render(request,\'login.html\') def index(request): #获取当前已经登录的用户名字 v=request.COOKIES.get(\'username111\') if not v: return redirect(request,\'/login/\') return render(request,\'index.html\',{\'current_user\':v})
2.4 写前端 index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>欢迎登录:{{current_user}}</h1> </body> </html>
2.4 写前端 login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/login/" method="POST"> <input type="text" name="username" placeholder="用户名"/> <input type="password" name="pwd" placeholder="密码"/> <input type="submit"/> </form> </body> </html>
2.5 效果
没有登录之前,是无法访问index页面的。
只有先从login页面登录了以后,才能跳转到index页面。
3. 在Django里面给cookie提供了一些额外的功能。
request.COOKIES-------表示用户发来数据的时候,它里面带的所携带的所有cookie信息。。。从请求中获取cookie
def cookie(request):
#用户发来请求时,它里面所携带的所有的cookie信息
request.COOKIES
request.COOKIES[\'username111\']
request.COOKIES.get(\'username111\')
设置cookie 键-值对
response.set_cookie(\'key\',\'value\')
def cookie(request): #用户发来请求时,它里面所携带的所有的cookie信息 request.COOKIES request.COOKIES[\'username111\'] request.COOKIES.get(\'username111\')
response=render(request,\'index.html\') #通过render,redirect把内容返回给浏览器 response=redirect(\'/index/\') #设置cookie,关闭浏览器后就失效
response.set_cookie(\'key\',\'value\') #还可以设置新的cookie 键-值对,也一并返回给浏览器
return response #里面不仅包含了内容,还包含了cookie的键-值对。
4. 默认情况下,关闭浏览器后,cookie就失效了,需要重新登录了。通过下面几种方法可以设置失效时间。
设置用户名和密码的失效时间-方法1,max_age=None
--------res.set_cookie(\'username111\',u,max_age=10) 设置失效时间为10秒
效果:10秒之后,用户名和密码就失效了,从index自动倒退回到login界面,需要重新登录了。
5. 设置用户名和密码的失效时间-方法2,expires=None
import datetime
current_date=datetime.datetime.utcnow()
current_daate=current_date+datetime.timedelta(seconds=5)
response.set_cookie(\'username111\', "value", expires=current_date)
6. 其它属性
设置cookie的生效路: ---path=\'/\',意思是在所有的url中都生效。path=\'/index\' 指只在index页面有效。
生效的域名: domain=None
https传输: secure=False
httponly: 只支持http传输,在JS前端是无法获取的,没有安全不安全一说。示例如下:
设置2个cookie,其中1个有httponly=True属性,对比看效果
在页面上访问的时候,看到了2个cookie
但是在前端却获取不到
7. 增加2个月内免登陆的功能,自己完成。把2个月换算成秒,添加到max_age=XXX里面就可以了。
注销的本质就是把cookie清除掉。
8. 完善实例,基于cookie实现定制显示数据条数
8.1----cookie在服务器端能读能写,在客户端也是能读能写的。
8.2----------jQuery有个插件叫jQuery-cookie,通过这个插件可以直接去浏览器上去操作cookie了。
从官网下载插件http://plugins.jquery.com/cookie/
8.3 用实例来验证,浏览器端确实可以获取到per_page_count这个值。
user_list.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .pagination .page{ display:inline-block; padding:5px; background-color:cyan; margin:5px; } .pagination .page.active{ background-color:brown; color:white; } </style> </head> <body> <ul> {% for item in li %} {% include \'li.html\' %} {%endfor%} </ul> <div> 请选择每页显示条数 <select id="ps" onchange="changePageSize(this)"> <option value="10">10</option> <option value="30">30</option> <option value="50">50</option> <option value="100">100</option> </select> </div> <div class="pagination"> {{page_str}} </div> <script src="/static/jquery-1.12.4.js"></script> <script src="/static/jquery.cookie.js"></script> <script> function changePageSize(ths){ var v=$(ths).val(); console.log(v); $.cookie(\'per_page_count\',v); } </script> </body> </html>
在Console中也可以看到这个效果。
8.4 服务器端从客户端传过来的cookie中获取到这个值。并且在实例化的时候,把它传递给类。
views.py
from django.shortcuts import render,HttpResponse,redirect from utils import pagination from django.urls import reverse # Create your views here. LIST=[] for i in range(1000): LIST.append(i) def user_list(request): current_page=request.GET.get(\'p\') current_page = int(current_page) val=request.COOKIES.get(\'per_page_count\') print(val) val=int(val) page_obj=pagination.Page(current_page,len(LIST),val) data=LIST[page_obj.start:page_obj.end] page_str=page_obj.page_str("/user_list/") return render(request,\'user_list.html\',{\'data\':data,\'page_str\':page_str}) user_info = { \'dachengzi\': {\'pwd\': "123123"}, \'kanbazi\': {\'pwd\': "kkkkkkk"}, } def login(request): if request.method == \'GET\': return render(request, \'login.html\') if request.method == \'POST\': u = request.POST.get(\'username\') p = request.POST.get(\'pwd\') dic = user_info.get(u) if not dic: return render(request, \'login.html\') if dic[\'pwd\'] == p: res = redirect(\'/index/\') res.set_cookie(\'username111\', u) return res else: return render(request, \'login.html\') def index(request): # 获取当前已经登录的用户名字 v = request.COOKIES.get(\'username111\') if not v: return redirect(request, \'/login/\') return render(request, \'index.html\', {\'current_user\': v})
8.5 完善功能。用户选中每页显示多少条,浏览器上就显示多少条。
代码修改如下:
8.6 完善功能,指定生效的url路径
var v=$.cookie(\'per_page_count\',{\'path\':"/user_list/"}); 指定路径
9. 至此,程序粘贴如下:
urls.py
from django.conf.urls import url from django.contrib import admin from app_ch import views urlpatterns = [ url(r\'^admin/\', admin.site.urls), url(r\'^user_list/$\', views.user_list), url(r\'^login\', views.login), url(r\'^index\', views.index), ]
views.py
from django.shortcuts import render,HttpResponse,redirect from utils import pagination from django.urls import reverse # Create your views here. LIST=[] for i in range(1000): LIST.append(i) def user_list(request): current_page=request.GET.get(\'p\') current_page = int(current_page) val=request.COOKIES.get(\'per_page_count\') print(val) val=int(val) page_obj=pagination.Page(current_page,len(LIST),val) data=LIST[page_obj.start:page_obj.end] page_str=page_obj.page_str("/user_list/") return render(request,\'user_list.html\',{\'data\':data,\'page_str\':page_str}) user_info = { \'dachengzi\': {\'pwd\': "123123"}, \'kanbazi\': {\'pwd\': "kkkkkkk"}, } def login(request): if request.method == \'GET\': return render(request, \'login.html\') if request.method == \'POST\': u = request.POST.get(\'username\') p = request.POST.get(\'pwd\') dic = user_info.get(u) if not dic: return render(request, \'login.html\') if dic[\'pwd\'] == p: res = redirect(\'/index/\') res.set_cookie(\'username111\', u) return res else: return render(request, \'login.html\') def index(request): # 获取当前已经登录的用户名字 v = request.COOKIES.get(\'username111\') if not v: return redirect(request, \'/login/\') return render(request, \'index.html\', {\'current_user\': v})
pagination.py
from django.utils.safestring import mark_safe class Page: def __init__(self,current_page,data_count,per_page_count=10,pager_num=7): self.current_page=current_page self.data_count=data_count self.per_page_count=per_page_count self.pager_num=pager_num @property def start(self): return (self.current_page - 1) * self.per_page_count @property def end(self): return self.current_page*self.per_page_count @property def total_count(self): v, y = divmod(self.data_count,self.per_page_count) if y: v = v+ 1 return v def page_str(self,base_url): page_list = [] if self.total_count < self.pager_num: start_index = 1 end_index = self.total_count + 1 else: if self.current_page <= (self.pager_num + 1) / 2: start_index = 1 end_index = self.pager_num + 1 else: start_index = self.current_page - (self.pager_num - 1) / 2 end_index = self.current_page + (self.pager_num + 1) / 2 if (self.current_page + (self.pager_num - 1) / 2) > self.total_count: end_index = self.total_count + 1 start_index = self.total_count - self.pager_num + 1 if self.current_page == 1: prev = \'<a class="page" href="javascript:void(0)">上一页</a>\' else: prev = \'<a class="page" href="%s?p=%s">上一页</a>\' % (base_url,self.current_page - 1) page_list.append(prev) for i in range(int(start_index), int(end_index)): if i == self.current_page: temp = \'<a class="page active" href="%s?p=%s">%s</a>\' % (base_url,i, i) else: temp = \'<a class="page" href="%s?p=%s">%s</a>\' % (base_url,i, i) page_list.append(temp) if self.current_page == self.total_count: nex = \'<a class="page" href="javascript:void(0);">下一页</a>\' else: nex = \'<a class="page" href=%s?p=%s>下一页</a>\' % (base_url,self.current_page + 1) page_list.append(nex) jump = \'\'\' <input type=\'text\'/><a onclick=\'jumpTo(this,"%s?p=");\'>Go</a> <script> function jumpTo(ths,base){ var val=ths.previousSibling.value; location.href=base+val; } </script> \'\'\'%(base_url) page_list.append(jump) page_str = mark_safe("".join(page_list)) return page_str
user_list.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .pagination .page{ display:inline-block; padding:5px; background-color:cyan; margin:5px; } .pagination .page.active{ background-color:brown; color:white; } </style> </head> <body> <ul> {% for i in data%} <li>{{i}}</li> {% endfor %} </ul> <div> 选择每页显示的条数: <select id="ps" onchange="changePageSize(this)"> <option value="10">10</option> <option value="30">30</option> <option value="50">50</option> </select> </div> <div class="pagination"> {{page_str}} </div> <script src="/static/jquery-1.12.4.js"></script> <script src="/static/jquery.cookie.js"></script> <script> $(function(){ var v=$.cookie(\'per_page_count\',{\'path\':"/user_list/"}); $(\'#ps\').val(v); }); function changePageSize(ths){ var v=$(ths).val(); $.cookie(\'per_page_count\',v,{\'path\':"/user_list/"}); location.reload(); } </script> </body> </html>
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/login/" method="POST"> <input type="text" name="username" placeholder="用户名"/> <input type="password" name="pwd" placeholder="密码"/> <input type="submit"/> </form> </body> </html>
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>欢迎登录:{{current_user}}</h1> </body> </html>
10. 带签名的cookie
-------明文:
获取cookie: request.COOKIES.get(\'......\')
设置cookie: response.set_cookie(.....)
--------密文:
加密解密如下,注意盐要对应,否则解密会不成功。
obj=HttpResponse(\'s\') #返回给客户端的数据
obj.set_signed_cookie(\'username\',"kangbazi",salt=\'XXX\') 通过XXX这个字符串,对cookie的内容进行加密。
request.get_signed_cookie(\'username\',salt="XXX") 服务器端获取得时候,需要解密。
11. 用装饰器实现用户验证
假设这里不仅有index页面需要验证,然后还有一个order页面也需要验证。我们尝试用装饰器来实现。
新建1个order页面,用FBV装饰器来实现。
用另外一种方法CBV实现
现在还没有登录,尝试用get访问的时候,效果如下:
在dispatch方法执行完了以后,才执行下面的方法。
from django.shortcuts import render,HttpResponse,redirect from utils import pagination from django.urls import reverse # Create your views here. LIST=[] for i in range(1000): LIST.append(i) def user_list(request): current_page=request.GET.get(\'p\') current_page = int(current_page) val=request.COOKIES.get(\'per_page_count\') print(val) val=int(val) page_obj=pagination.Page(current_page,len(LIST),val) data=LIST[page_obj.start:page_obj.end] page_str=page_obj.page_str("/user_list/") return render(request,\'user_list.html\',{\'data\':data,\'page_str\':page_str}) user_info = { \'dachengzi\': {\'pwd\': "123123"}, \'kanbazi\': {\'pwd\': "kkkkkkk"}, } def login(request): if request.method == \'GET\': return render(request, \'login.html\') if request.method == \'POST\': u = request.POST.get(\'username\') p = request.POST.get(\'pwd\') dic = user_info.get(u) if not dic: return render(request, \'login.html\') if dic[\'pwd\'] == p: res = redirect(\'/index/\') res.set_cookie(\'username111\', u) return res else: return render(request, \'login.html\') def auth(func): def inner(request,*args,**kwargs): v = request.COOKIES.get(\'username111\') if not v: return redirect(request, \'/login/\') return func(request,*args,**kwargs) return inner @auth def index(request): # 获取当前已经登录的用户名字 v = request.COOKIES.get(\'username111\') return render(request, \'index.html\', {\'current_user\': v}) from django import views from django.utils.decorators import method_decorator class Order(views.View): @method_decorator(auth) def dispatch(self,request,*args,**kwargs): return super(Order,self).dispatch(request,*args,**kwargs) def get(self,request): v = request.COOKIES.get(\'username111\') return render(request, \'index.html\', {\'current_user\': v}) def post(self,request): v = request.COOKIES.get(\'username111\') return render(request, \'index.html\', {\'current_user\': v}) def order(request): # 获取当前已经登录的用户名字 v = request.COOKIES.get(\'username111\') return render(request, \'index.html\', {\'current_user\': v})
可以更优化,把装饰器写到类的上面。
FBV和CBV两种方法实现装饰器的比较
至此程序如下:
urls.py
from django.conf.urls import url from django.contrib import admin from app_ch import views urlpatterns = [ url(r\'^admin/\', admin.site.urls), url(r\'^user_list/$\', views.user_list), url(r\'^login\', views.login), url(r\'^index\', views.index), url(r\'^order\', views.Order.as_view()), ]
views.py
from django.shortcuts import render,HttpResponse,redirect from utils import pagination from django.urls import reverse # Create your views here. LIST=[] for i in range(1000): LIST.append(i) def user_list(request): current_page=request.GET.get(\'p\') current_page = int(current_page) val=request.COOKIES.get(\'per_page_count\') print(val) val=int(val) page_obj=pagination.Page(current_page,len(LIST),val) data=LIST[page_obj.start:page_obj.end] page_str=page_obj.page_str("/user_list/") return render(request,\'user_list.html\',{\'data\':data,\'page_str\':page_str}) user_info = { \'dachengzi\': {\'pwd\': "123123"}, \'kanbazi\': {\'pwd\': "kkkkkkk"}, } def login(request): if request.method == \'GET\': return render(request, \'login.html\') if request.method == \'POST\': u = request.POST.get(\'username\') p = request.POST.get(\'pwd\') dic = user_info.get(u) if not dic: return render(request, \'login.html\') if dic[\'pwd\'] == p: res = redirect(\'/index/\') res.set_cookie(\'username111\', u) return res else: return render(request, \'login.html\') def auth(func): def inner(request,*args,**kwargs): v = request.COOKIES.get(\'username111\') if not v: return redirect(request, \'/login/\') return func(request,*args,**kwargs) return inner @auth def index(request): # 获取当前已经登录的用户名字 v = request.COOKIES.get(\'username111\') return render(request, \'index.html\', {\'current_user\': v}) 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(\'username111\') return render(request, \'index.html\', {\'current_user\': v}) def post(self,request): v = request.COOKIES.get(\'username111\') return render(request, \'index.html\', {\'current_user\': v}) def order(request): # 获取当前已经登录的用户名字 v = request.COOKIES.get(\'username111\') return render(request, \'index.html\', {\'current_user\': v})
utils-->pagination.py
from django.utils.safestring import mark_safe class Page: def __init__(self,current_page,data_count,per_page_count=10,pager_num=7): self.current_page=current_page self.data_count=data_count self.per_page_count=per_page_count self.pager_num=pager_num @property def start(self): return (self.current_page - 1) * self.per_page_count @property def end(self): return self.current_page*self.per_page_count @property def total_count(self): v, y = divmod(self.data_count,self.per_page_count) if y: v = v+ 1 return v def page_str(self,base_url): page_list = [] if self.total_count < self.pager_num: start_index = 1 end_index = self.total_count + 1 else: if self.current_page <= (self.pager_num + 1) / 2: start_index = 1 end_index = self.pager_num + 1 else: start_index = self.current_page - (self.pager_num - 1) / 2 end_index = self.current_page + (self.pager_num + 1) / 2 if (self.current_page + (self.pager_num - 1) / 2) > self.total_count: end_index = self.total_count + 1 start_index = self.total_count - self.pager_num + 1 if self.current_page == 1: prev = \'<a class="page" href="javascript:void(0)">上一页</a>\' else: prev = \'<a class="page" href="%s?p=%s">上一页</a>\' % (base_url,self.current_page - 1) page_list.append(prev) for i in range(int(start_index), int(end_index)): if i == self.current_page: temp = \'<a class="page active" href="%s?p=%s">%s</a>\' % (base_url,i, i) else: temp = \'<a class="page" href="%s?p=%s">%s</a>\' % (base_url,i, i) page_list.append(temp) if self.current_page == self.total_count: nex = \'<a class="page" href="javascript:void(0);">下一页</a>\' else: nex = \'<a class="page" href=%s?p=%s>下一页</a>\' % (base_url,self.current_page + 1) page_list.append(nex) jump = \'\'\' <input type=\'text\'/><a onclick=\'jumpTo(this,"%s?p=");\'>Go</a> <script> function jumpTo(ths,base){ var val=ths.previousSibling.value; location.href=base+val; } </script> \'\'\'%(base_url) page_list.append(jump) page_str = mark_safe("".join(page_list)) return page_str
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/login/" method="POST"> <input type="text" name="username" placeholder="用户名"/> <input type="password" name="pwd" placeholder="密码"/> <input type="submit"/> </form> </body> </html>
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>欢迎登录:{{current_user}}</h1> </body> </html>
以上是关于Day21-Cookie的主要内容,如果未能解决你的问题,请参考以下文章
sqli-labs less21 Cookie Injection- Error Based- complex - string ( 基于错误的复杂的字符型Cookie注入)