cookie与session,Django中间件,跨站请求伪造
一.cookie与session
Cookie的由来
因为HTTP协议是无状态的,就是说你没次访问一个网站就像是第一次访问.因此就诞生的Cookie.
什么是Cookie
Cookie具体指的是一小段信息,它是由服务器发出来的存储在浏览器上的一组组的键值对,当你的浏览器下次再访问时,就会携带这些信息,以便服务器来提取有用的信息.
Cookie
cookie的工作原理: 由服务器产生的内容,浏览器收到请求后保存在本地,当浏览器再次访问时,浏览器会自动的带上cookie,这样服务器通过cookie来判定,你是不是来过.
二.Django中操作Cookie
获取Cookie
request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
参数:
- default: 默认值
- salt: 加密盐
- max_age: 后台控制过期时间
设置Cookie
rep = HttpResponse(...)
rep = render(request, ...)
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐', max_age=None,...)
参数:
- key: 键
- value: 值
- max_age=None: 超时时间
删除Cookie
def logout(request):
rep = redirect("/login/")
rep.delete_cookie("user") #删除用户浏览器上之前设置的usercookie值
return rep
Cookie实现登录认证
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'kang' and password == '123':
old_path = request.GET.get('next') # 拿到要访问的页面
if old_path:
obj = redirect(old_path) #如果有就返回那个页面
else:
obj = redirect('/home/')
obj.set_cookie('name','kang') # 让客户端浏览器记录一个键值对
return obj
return render(request, 'login.html')
# 登录装饰器
from functools import wraps
def login_auth(func):
@wraps(func)
def inner(request,*args, **kwargs):
if request.COOKIES.get('name'): #判断有没有cookie,有的话直接返回
res = func(request,*args, **kwargs)
return res
else:
target_url = request.path_info # 没有的跳转到登录页,并且附带上想要访问的
return redirect('/login/?next=%s'%target_url)
return inner
@login_auth
def home(request):
return HttpResponse('我是主页面,登录后查看')
@login_auth
def index(request):
return HttpResponse('我是买东西页面')
@login_auth
def play(request):
return HttpResponse('我是玩游戏页面')
@login_auth
def logout(request):
obj = redirect('/login/')
obj.delete_cookie('name')
return obj
Session
Session的由来
- Cookie虽然能够帮助我们解决需求,但是他本身最大支持4096字节,因为他是存在客户端的,所以也有可能被拦截或者窃取.因此出现了Session,它是存放在服务器端,并且有较高的安全性.
- 基于HTTP协议的无状态特征,服务器根本就不知道访问者,那么Cookie就起到了桥接的作用.
- 我们可以给没个客服端的Cookie分配一个唯一的id,这样在访问时,通过Cookie,服务器就知道来的人是'谁',然后在根据不同的Cookie的id,在服务器上保存一段时间的信息.如"账号密码".
- Cookie弥补了HTTP无状态的不足,让服务器知道了来的人是谁,但是Cookie是以文本的形式保存在本地.自身安全性较差,所以我们就通过Cookie识别不同的用户,对应的在Session保存私密的信息以及超过4096的字节文本.
- 所有说,Cookie和Session是共通性的东西.
Django中的Session相关方法
# 设置,获取,删除session中的数据
#设置
request.session['username'] = 'kang'
#获取
request.session.get('username')
#删除
request.session.flush()
#设置会话Session和Cookie的超时时间
request.session.set_expiry(value)
如果value是个整数,session会在这些秒数后失效
如果value是0,用户关闭浏览器就会失效.
Session实现登录认证
Django中间件
中间件的作用
- 用户访问频率限制
- 用户是否是黑名单,白名单
- 所有用户登录校验
- 只要是涉及到网址全局的功能,你就应该考虑使用中间件.
django中间件暴露给程序员的五个可以自定义的方法(五个方法都是在特定的条件下自定触发的)
1.你要新建一个文件夹, 里面可以建立任意名称的py文件
里面写类固定继承
from django.utils.deprecation import MiddlewareMixin
class MyThink(MiddlewareMixin):
#五个方法:
需要掌握的:
1. process_request(******):请求来的时候 会从上往下依次经过每一个中间件里面process_request,一旦里面返回了HttpResponse对象那么就不再往后执行了,会执行同一级别的process_response
def process_request(self,request):
print('我是第一个自定义中间件里面的process_request方法')
return HttpResponse("我是第一个自定义中间件里面的HttpResponse对象返回值") # 直接原地返回
2.process_response(***):响应走的时候 会从下往上依次进过每一个中间件里面的process_response
def process_response(self,request,response): # response就是要返回给用户的数据
print("我是第一个自定义中间件里面的process_response方法")
return response
了解的:
process_view:路由匹配成功之后执行视图函数之前触发
process_exception:当视图函数出现异常(bug)的时候自动触发
process_template_response:当视图函数执行完毕之后并且返回的对象中含有render方法的情况下才会触发
跨站请求伪造(钓鱼网站)
就相当于你搭建了一个和充Q币一模一样的网站,用户在你的网站进行充值的时候输入的是自己的结果充给了你.
简单的原理
- 在你写form表单的时候,用户的用户名,密码都会真实的提交给Q币后台
- 但是被充的人的账户却不是用户填的,你暴露给用户的是一个没有name属性的input框
- 你自己写好了一个隐藏的带有的name和value的input框
解决钓鱼网站的策略
- 只要是用户想要提交post请求的页面,我在返回给用户的时候就提前设置好一个随机字符串
- 当用户提交post请求的时候,我会自动先获取查找是否有该随机的字符串.
- 如果有正常提交,否则直接报403
form表单
你在写form表单的时候只需要加上
{% csrf_token %}
ajax
第一种: 自己在页面上先通过{% cstf_token %}获取到随机字符串,然后利用标签查找
data: {'username':'kang','csrfmiddlewaretoke:$([name="csrfmiddlewaretoken"]').val()}
第二种:
data:{'username':'kang', 'csrfmiddlewaretoken':'{{ csrf_token }}'}
第三种
拷贝js文件
如何不校验使用装饰器
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator # 它作用于CBV
@csrf_exempt # 避免校验
def exem(request):
return HttpResponse('exempt')
@csrf_protect # 可单独校验
def pro(request):
return HttpResponse('pro')
CBV
from django.views import View
# 第一种
# @method_decorator(csrf_exempt,name='dispatch')
@method_decorator(csrf_protect,name='post')
class MyCsrf(View):
# 第二种
# @method_decorator(csrf_exempt)
@method_decorator(csrf_protect)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return HttpResponse('hahaha')
@method_decorator(csrf_protect)
def post(self,request):
return HttpResponse('post')