cookie和中间件
作业讲解
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')
return res
return render(request, 'login.html')
django操作cookie
set_signed_cookie(key,value,salt='加密盐')
set_signed_cookie(key,value,max_age=超时时间:默认是秒数)
expires:专门针对IE浏览器设置超时时间
HttpResponse对象.delete_cookie(key) 直接删除
ps:学到这里要对登录操作有本质的认识:核心就是cookie的存取
django操作session
* 设置
request.session['key'] = value 设置相关的cookie
request.session['name'] = 'jason'
可以设置多组相关的字符串
* 获取
request.session.get('key',None)
request.session.get('name') # jason 是一串密文
session是键值配对的形式保存在客户端端口的 所以取值也以get取值
也可以直接键值配对设置 获取数据是获取多组数据
* 没有存储的情况下取值会报错 no such table django_session
django_session 是一张表 是django自带的表
在django迁移命令的时候会产生很多表在MySQL中是django_session
表中只有 三个字符段 session_key[关键字参数] session_data[数据信息] session_date[过期日期]
* * 流程:
1. 产生一个随机的字符串、
2. 表中存储随机的字符串与加密数据的对应关系 并将产生的随机字符串发送到客户端保存
ps:django默认的过期时间是14天
cookie和session的区别 session会加密 cookie直接保存在客户端的键值对便于识别
request.session.setdefault('k1',123) # 存在则不设置 不会报错
* 删除 和字典类似直接通过删除键来删除
del request.session['k1']
* session内部发送事件
res = request.session.get('name')
print(res)
return HttpResponse('拿值操作')
会将加密的随机字符串解码
1.自动获取客户端请求中的随机字符串
2.自动去存储session数据的表中比对
3.如果比对成功自动获取并'解密处理'
* 特殊的操作
request.session.session_key # 获取产生的随机字符串
request.session.delete() # 只删客户端
request.session.flush() # 服务端 客户端都删
request.session.set_expiry(value) # 设置超时时间
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。
针对session数据的存储位置 有五种方案
1.数据库存储
2.缓存存储
3.文件存储
4.缓存+数据库存储
5.动态加密
CBV添加装饰器
CBV装饰器需要专门的装饰器 函数装饰器不适应与类 fbv适合加入函数装饰器
CBV添加装饰器有三种方法:
* frist:
from django.utils.decorators import method_decorator
from django import views
class My_login(views.View):
@method_decorator(login_uth)
def get(self,request):
return HttpResponse('from CBV get view')
def post(self,request):
return HttpResponse('from CBV post view')
* secend:
@method_decorator(login_uth,name='使用装饰器的函数名')
class .....
* third:重写dispatch方法
views源码也用作dispatch方法
@method_decorator(login_uth)
def dispatch(self, request, *args, **kwargs):
super().dispatch(request,*args,**kwargs)
将@method_decorator(login_uth)添加到dispatch函数上方
django中间件
简介
# 回忆django请求生命周期流程图
是django的门户 自带七个中间件 每个都有各自对应的功能
也就是在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',
]
本质是上各个中间件都是模块 django不单有七个中间件并且每个都有很多功能和方法,除此之外django还支持自定义中间件并提供五个可以自定义的方法
django提供了五个自定义的方法:
process_request
process_response
process_view
process_tmplate_response
prrcess_excepton
django中间件的使用场景:只要是全局相关的功能都可以在中间件中编写
eg:用户黑名单校验、用户访问频率校验、网站全局用户身份校验
黑名单的数据校验可以做成post请求直接在中间件返回客户端
必要点
"""
1.创建一个任意名称的文件夹
2.在该文件夹内创建一个任意名称的py文件
3.在该py文件内编写中间件类 # 中间类的编写可以参考settings文件的模块配置
from django.utils.deprecation import MiddlewareMixin
主要配置的模块文件
4.配置文件中注册 # 注册文件在settings
"""
1. process_request
from django.utils.deprecation import MiddlewareMixin
class myidd(MiddlewareMixin):
def process_request(self,request):
print('my 返回值1 my_process') # 执行视图函数之前展示
views视图层
def lss(request):
print('视图函数angelbaby') # 执行函数之后打印
return HttpResponse('视图函数值')
请求来的时候会从上往下依次执行配置文件中注册了的中间件里面的process_request方法 如果没有则直接跳过
如果该方法自己返回了HttpResponse对象,那么请求不再继续往后直接返回相应的数据
2. process_response
def process_response(self,request,response):
print('返回值 my_response')
return response
* * 配合process_request不能在创建的类里面添加HttpResponse否则会打断函数运行
类中HttpResponse会将自身的值直接返回
* 底层需要三个形参进行接收
响应走的时候会从下往上依次执行配置文件中注册了的中间件里面的process_response方法 如果没有则直接跳过
如果该方法自己返回了HttpResponse对象,那么响应会替换成该HttpResponse对象数据 而不再是视图函数想要返回给客户端的数据
"""如果process_request返回了HttpResponse对象 那么会从当前位置从下往上执行每一个process_response"""
需要了解的方法
1.process_view
路由匹配成功之后执行视图之前从上往下执行配置文件中注册了的中间件里面的process_view方法
2.process_template_response
视图函数执行完毕之后返回的对象中含有render属性对应一个render方法
则会从下往上执行配置文件中注册了的中间件里面的process_template_response方法
3.process_exception
视图函数执行过程中报错并在返回响应的时候会从下往上执行配置文件中注册了的中间件里面的process_exception
csrf跨站请求伪造数据
* 其实就是运用中间件的方法对网站进行防爬和加密
主要是防止钓鱼网站:
钓鱼网站:一个模仿正规网站的网址 诱骗用户在该网站上做本应该在正规网站上做的操作,从而获取到该用户在正规网站上的数据甚至是财产
eg:假设我们需要登录网页完成转账操作
我们不小心登录到了钓鱼网站 填写了账户 密码 对方账户等信息
点击转账之后我们账户的钱确实减少了 但是对方账户却变成了一个你从来不认识的人
原理:将收款人的账号 提前写成犯罪分子的然后隐藏 暴露给用户一个没有name属性的标签写着玩
ps:其实就是诈骗
这是真实网站:
def ad_csrf(request):
if request.method == 'POST':
current_name = request.POST.get('current_name')
target_name = request.POST.get('target_name')
money = request.POST.get('money')
return HttpResponse(f'用户{current_name}给账户{target_name}转账{money}')
return render(request,'FuncA.html',locals())
罪犯爬了一个下来:
只需要将真实转账的地址换上即可 然后在
target_name = request.POST.get('target_name')的html对应页面上直接进行添加values操作
csrf解决策略
"""针对csrf相关的校验有很多种方式 django只是提供了一些而已"""
# form表单
<form action="" method="post">
{% csrf_token %}
<p>当前账户:<input type="text" name="current_user"></p>
<p>目标账户:<input type="text" name="target_user"></p>
<p>转账金额:<input type="text" name="money"></p>
<input type="submit">
</form>
# ajax请求
1.方式1:页面任意位置先写{% csrf_token %} 之后获取数据
data:{'current_name':$('input[name="current_name"]').val(),
'target_name':$('input[name="target_name"]').val(),
'money':$('input[name="money"]').val()},
* 'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()
将相关数据传入即可 ajax校验主要用于校检css请求
2.方式2:模板语法直接获取
'csrfmiddlewaretoken':{{ csrf_token }}
"""通用解决方案:js脚本自动处理"""
也只能适用于ajax提交 form表单还是需要额外指定