django操作cookie django操作session CBV添加装饰器 django中间件 csrf跨站请求伪造
作者:互联网
day 60
作业讲解
作业需求:
用户登录之后跳转到用户登陆之前想要访问的页面
提示:
利用url问号携带参数
# 装饰器
def login_auth(func_name):
def inner(request, *args, **kwargs):
# print(request.path) # 获取路径
# print(request.path_info) # 获取路径信息
# 1.获取用户没有登录之前想要访问的网址地址
target_path = request.get_full_path()
if request.COOKIES.get('name'):
res = func_name(request, *args, **kwargs)
return res
else:
# 2.将用户想要访问的地址当做参数传给登录功能
return redirect(f'/login/?next={target_path}')
return inner
# 登录功能
def login(request):
if request.method == 'POST':
name = request.POST.get("name")
if name == 'jason':
# 获取用户登录之前想要访问的地址
next_path = request.GET.get('next')
'''注意 用户也有可能直接访问的登录页面 没有想要访问的其他页面'''
if next_path:
res = redirect(next_path) # 跳转到之前想要访问的界面
else:
res = redirect('/home/') # 默认登录之后跳转的界面
res.set_cookie('name', 'jason') # 让浏览器记录cookie数据 设置cookie 告诉浏览器存一个k:v键值对
"""
1.浏览器不单单会帮你存
2.而且后面每次访问你的时候还会带着它过来
"""
return res
return render(request, 'login.html')
解决思路:
1.在装饰器login_auth内设置一个获取用户上一次想访问的url
2.将用户想访问的url放在当作参数get请求重定向发送给login
3.login获取用户想访问的url,然后判断生成对象,重定向返回!
django操作cookie补充
设置Cookie
salt
: 加密盐
# 代码演示
def login(request):
if request.method == 'POST':
name = request.POST.get("name")
if name == 'jason':
# 获取用户登录之前想要访问的地址
next_path = request.GET.get('next')
'''注意 用户也有可能直接访问的登录页面 没有想要访问的其他页面'''
if next_path:
res = redirect(next_path) # 跳转到之前想要访问的界面
else:
res = redirect('/home/') # 默认登录之后跳转的界面
# res.set_cookie('name', 'jason')
res.set_signed_cookie('name', 'jason',salt='你好啊',max_age=3) # 设置超时时间3秒 到时候自动清除cookie
return res
return render(request, 'login.html')
解析Cookie设置超时时间两者方法区别:
max_age
expires
1.两者都是设置超时时间的 并且都是以秒为单位
2.针对IE浏览器需要使用expires
注销功能 主动删除cookie
delete_cookie
HttpResponse对象.delete_cookie(key)
# 代码演示
# 在你登录后如果想要退出 可以进行删除cookie操作 删除后 就无法再直接访问了
@login_auth
def logout(request):
res = redirect('/login/')
res.delete_cookie('name') # 删除本地cookie'name'
return res # 删除后 返回到登录页面
ps:学到这里要对登录操作有本质的认识:核心就是cookie的存取
django操作session
以后我们经常处理的还是session 因为cookie采用的是以明文规定为主 而session采用的是密文
# 设置request.session['key'] = value
# 可以设置多组
eg:
def set_session(request):
request.session['name1'] = '周二了还有三天周末了'
request.session['name2'] = '儿童节放不放假'
request.session['name3'] = '端午节放不放假'
return HttpResponse("set_session操作")
session工作机制
服务端保存用户相关状态信息 返回给客户端随机字符串
针对保存 django需要一张表来处理 >>> 自带的django_session表
ps:
如何查看到这张表
通过django数据库迁移命令会产生一堆默认的表
其中就有一张django_session表
设置session内部发生的事情
第一步:产生一个随机字符串
第二步:表中存储随机字符串与加密数据的对应关系
第三步:并将产生的随机字符串也给客户端发送一份并让其保存
客户端会以 sessionid:随机字符串 形式保存
把随机字符串给了客户端,客户端浏览器下次访问的时候就会拿着这个字符串去django_session表中做比对
比对成功就可以拿到服务端存储的数据,这样做的好处就是避免了客户端浏览器信息泄露
# django默认的session失效时间是14天
# 获取request.session.get('key')
# 可以获取多组
eg:
def get_session(request):
res1 = request.session.get('name1')
res2 = request.session.get('name2')
res3 = request.session.get('name3')
print(res1, res2, res3)
print(request.session.session_key)
return HttpResponse('get_session操作')
获取session内部发送的事情
第一步:自动获取客户端请求中的随机字符串
第二步:自动去存储session数据的表中比对
第三步:如果比对成功自动获取并'解密处理'
django操作session补充
request.session.session_key
# 获取k值 就是产生的随机字符串request.session.delete()
# 只删客户端 就是删除当前会话的session数据request.session.flush()
# 服务端 客户端都删 就是删除当前会话的session与cookie数据request.session.set_expiry(value)
# 设置超时时间
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。默认14天
针对session数据的存储位置
有五种方案:
1.数据库存储(默认)
2.缓存存储
3.文件存储
4.缓存+数据库存储
5.动态加密
CBV添加装饰器
'''需要借助于一个专门的装饰器模块'''
from django.utils.decorators import method_decorator
# 方式1:利用模块 直接在类中的对应的方法上直接添加
class MyLoginView(views.View):
@method_decorator(login_auth) # 在装饰器方法后面放入需要使用的装饰器
def get(self, request):
return HttpResponse("from CBV get view")
# 方式2:直接在类名上添加并指定
@method_decorator(login_auth, name='get') # 在装饰器方法括号内放入 要使用的装饰器,类中需要添加装饰器的方法 比如说get方法
class MyLoginView(views.View):
def get(self, request):
return HttpResponse("from CBV get view")
# 方式3:重写dispatch方法并添加作用于类中所有的方法(全局)
class MyLoginView(views.View):
@method_decorator(login_auth)
"""
给自己写的dispatch装了装饰器后
整个CBA里面所有的方法都需要经过这个装饰器的校验
因为CBA所有方法执行之前都要先执行dispatch
"""
def dispatch(self, request, *args, **kwargs): # 先走自己写的dispatch
super().dispatch(request,*args,**kwargs) # 再走类里面的dispatch
django中间件
# 回忆django请求生命周期流程图
是django的门户 自带七个中间件 每个都有各自对应的功能
django不单有七个中间件并且每个都有很多功能和方法,
除此之外django还支持自定义中间件并提供五个可以自定义的方法
process_request
process_response
process_view
process_template_response
process_excepton
django中间件的使用场景:
只要是全局相关的功能都可以在中间件中编写
eg:
用户黑名单校验、用户访问频率(爬虫的防爬措施)校验、网站全局用户身份校验
# settings:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', # session中间件 如果注了就无法使用该功能
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
自定义中间件
如何让创建中间件?
1.在应用下创建一个任意名称的文件夹
2.在该文件夹内创建一个任意名称的py文件
3.在该py文件内编写中间件类
4.配置文件中注册
通过看django里的配置文件里面的中间件源码得知,自定义中间件需要是定义一个类,然后继承MiddlewareMixin
如何注册中间件?
# 必须要掌握的方法
process_request方法
第一个特征:请求来的时候会从上往下依次执行配置文件中注册了的中间件里面的process_request方法 如果没有则直接跳过
第二个特征:如果该方法自己返回了HttpResponse对象,那么请求不再继续往后直接返回相应的数据 因为被拦截了
process_response方法
第一个特征:响应走的时候会从下往上依次执行配置文件中注册了的中间件里面的process_response方法 如果没有则直接跳过
固定写法:有两个形参,必须返回response
第二个特征:如果该方法自己返回了HttpResponse对象,那么响应会替换成该HttpResponse对象数据 而不再是视图函数想要返回给客户端的数据 中途被HttpResponse对象拦截了
"""如果process_request返回了HttpResponse对象 那么会从当前位置(原路返回)从下往上执行每一个process_response"""
# 需要了解的方法
process_view方法
路由匹配成功之后执行视图之前从上往下执行配置文件中注册了的中间件里面的process_view方法
process_template_response方法
视图函数执行完毕之后返回的对象中含有render属性对应一个render方法
则会从下往上执行配置文件中注册了的中间件里面的process_template_response方法
process_exception方法
视图函数执行过程中报错并在返回响应的时候会从下往上执行配置文件中注册了的中间件里面的process_exception 会打印错误信息
csrf跨站请求伪造
# 前戏
钓鱼网站:一个模仿正规网站的网址 诱骗用户在该网站上做本应该在正规网站上做的操作,从而获取到该用户在正规网站上的数据甚至是财产
eg:假设我们需要登录网页完成转账操作
我们不小心登录到了钓鱼网站 填写了账户 密码 对方账户等信息
点击转账之后我们账户的钱确实减少了 但是对方账户却变成了一个你从来不认识的人
原理:将收款人的账号 提前写成犯罪分子的然后隐藏 暴露给用户一个没有name属性的标签写着玩
# 简单模拟
开设两个django项目 模拟两个相同的页面 具体参考课上代码
csrf解决策略
服务端返回页面的时候做一个特殊标记 客户端往服务端发送请求的时候,服务端会先验证页面上是否有对应的特殊标记,如果有同意访问,没有的话,拒绝访问。
"""针对csrf相关的校验有很多种方式 django只是提供了一些而已""
form表单操作步骤:
第一步:解开注释
第二步:
利用模版语法 添加一句{% csrf_token %}
ajax请求操作步骤:
方式一:
页面任意位置先写{% csrf_token %} 之后获取数据
再编写 'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()
方式二:
模板语法直接获取
再编写'csrfmiddlewaretoken':{{ csrf_token }}
如果项目是前后端分离的 无法使用模版语法 那么有一个通用解决方案:js脚本自动处理
也只能适用于ajax提交 form表单还是需要额外指定
标签:跨站,get,process,中间件,request,django,session 来源: https://www.cnblogs.com/jiqiong/p/16322737.html