django操作cookie补充,django操作session,CBV添加装饰器,django中间件,自定义中间件
django操作cookie补充
set_signed_cookie(key,value,salt='加密盐')
set_signed_cookie(key,value,max_age=超时时间:默认是秒数)
expires:专门针对IE浏览器设置超时时间
#删除cookie
HttpResponse对象.delete_cookie(key)
django操作session
# 设置
request.session['key'] = value # 可以设置多组
# 获取
request.session.get('key') # 可以获取多组
"""
服务端保存用户相关状态信息 返回给客户端随机字符串
针对保存 django需要一张表来处理 >>> 自带的django_session表
ps:django数据库迁移命令会产生一堆默认的表 其中就有一张django_session表
"""
基本操作
以键值对的格式写 session request.session['键']=值
根据键读取值 request.session.get('键',默认值) # 或者 request.session['键']
清除所有 session,在存储中删除值的部分 request.session.clear() 清除 session 数据,
在存储中删除 session 的整条数据 request.session.flush() 删除 session 中的指定键及值,
在存储中只删除某个键及对应的值 del request.session['键']
设置 session 数据有效时间; 如果不设置,默认过期时间为两周 request.session.set_expiry(value)
如果过期时间的 value 是一个整数,则 session 数据 将在 value 秒没有活动后过期。
如果过期时间的 value 为 None,那么会话永不过期。
如果过期时间的 value 为 0,那么用户会话的 Cookie 将在用户的浏览器关闭时过期。
CBV添加装饰器
'''需要借助于一个专门的装饰器模块'''
from django.utils.decorators import method_decorator
装饰器
# 装饰器
def login_auth(func):
def inner(request, *args, **kwargs):
if request.session.get("is_login"):
res = func(*args, **kwargs)
return res
else:
return redirect('/login/')
return inner
第一种---直接在类中的某个方法上添加
class Index(View):
# 在每个需要验证的地方都加上装饰器
@method_decorator(login_auth)
def get(self, request):
print("get 请求")
return render(request, "index.html")
@method_decorator(login_auth)
def post(self, request):
print("post 请求")
return HttpResponse("post")
第二种---在类的上面加上,name为具体要加的函数
@method_decorator(login_auth, name='post')
@method_decorator(login_auth, name='get')
class Index(View):
def get(self, request):
print("get 请求")
return render(request, "index.html")
def post(self, request):
print("post 请求")
return HttpResponse("post")
第三种---重写dispatch方法并添加作用于类中所有的方法
class Index(View):
#方法三 使用dispatch给所有的方法添加装饰器
@method_decorator(login_auth)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
def get(self, request):
print("get 请求")
return render(request, "index.html")
def post(self, request):
print("post 请求")
return HttpResponse("post")
django中间件
什么是中间件
中间件,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出
由于它影响的是全局,所以需要谨慎使用,用不好会影响到性能
'''
如果你想修改请求,例如被传送到view中的HTTPResponse对象,或者你想修改HttpResponse对象,这些都可以通过中间件实现
如果你还想在view执行之前做一些操作,这种情况就可以用middleware来实现
'''
django中默认的中间件:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'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文件,并在该 py 文件中导入 MiddlewareMixin。
'''from django.utils.deprecation import MiddlewareMixin'''
3.在该py文件内编写中间件类,要继承父类 MiddlewareMixin
class MD1(MiddlewareMixin):
pass
4.在 settings.py 中的 MIDDLEWARE 里注册自定义的中间件类:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'app01.middlewares.MD1',
]
自定义中间件类的方法:process_request 和 process_response
process_request 方法
process_request 方法有一个参数 request,这个 request 和视图函数中的 request 是一样的。
process_request 方法的返回值可以是 None 也可以是 HttpResponse 对象。
返回值是 None 的话,按正常流程继续走,交给下一个中间件处理。
返回值是 HttpResponse 对象,Django 将不执行后续视图函数之前执行的方法以及视图函数,直接以该中间件为起点,倒序执行中间件,且执行的是视图函数之后执行的方法。
process_request 方法是在视图函数之前执行的。
当配置多个中间件时,会按照 MIDDLEWARE中 的注册顺序,也就是列表的索引值,顺序执行。
不同中间件之间传递的 request 参数都是同一个请求对象。
'''
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render, HttpResponse
class MD1(MiddlewareMixin):
def process_request(self, request):
print("md1 process_request 方法。", id(request)) #在视图之前执行
'''
process_response方法
process_response 方法有两个参数,一个是 request,一个是 response,request 是请求对象,response 是视图函数返回的 HttpResponse 对象,该方法必须要有返回值,且必须是response。
process_response 方法是在视图函数之后执行的。
当配置多个中间件时,会按照 MIDDLEWARE 中的注册顺序,也就是列表的索引值,倒序执行。
'''
class MD1(MiddlewareMixin):
def process_request(self, request):
print("md1 process_request 方法。", id(request)) #在视图之前执行
def process_response(self,request, response): :#基于请求响应
print("md1 process_response 方法!", id(request)) #在视图之后
return response
'''
正常的情况下按照绿色的路线进行执行,假设中间件1有返回值,则按照红色的路线走,直接执行该类下的 process_response 方法返回,后面的其他中间件就不会执行。
process_view方法
process_view 方法格式如下:
process_view(request, view_func, view_args, view_kwargs)
process_view 方法有四个参数:
request 是 HttpRequest 对象。
view_func 是 Django 即将使用的视图函数。
view_args 是将传递给视图的位置参数的列表。
view_kwargs 是将传递给视图的关键字参数的字典。
view_args 和 view_kwargs 都不包含第一个视图参数(request)。
process_view 方法是在视图函数之前,process_request 方法之后执行的。
返回值可以是 None、view_func(request) 或 HttpResponse 对象。
返回值是 None 的话,按正常流程继续走,交给下一个中间件处理。
返回值是 HttpResponse 对象,Django 将不执行后续视图函数之前执行的方法以及视图函
数,直接以该中间件为起点,倒序执行中间件,且执行的是视图函数之后执行的方法。
返回值是 view_func(request),Django 将不执行后续视图函数之前执行的方法,提前执行视
图函数,然后再倒序执行视图函数之后执行的方法。
当最后一个中间件的 process_request 到达路由关系映射之后,返回到第一个中间件
process_view,然后依次往下,到达视图函数。
'''
class MD1(MiddlewareMixin):
def process_request(self, request):
print("md1 process_request 方法。", id(request)) #在视图之前执行
def process_response(self,request, response): :#基于请求响应
print("md1 process_response 方法!", id(request)) #在视图之后
return response
def process_view(self,request, view_func, view_args, view_kwargs):
print("md1 process_view 方法!") #在视图之前执行 顺序执行
#return view_func(request)
'''
process_exception方法
process_exception 方法如下:
process_exception(request, exception)
参数说明:
request 是 HttpRequest 对象。
exception 是视图函数异常产生的 Exception 对象。
process_exception 方法只有在视图函数中出现异常了才执行,按照 settings 的注册倒序执行。
在视图函数之后,在 process_response 方法之前执行。
process_exception 方法的返回值可以是一个 None 也可以是一个 HttpResponse 对象。
返回值是 None,页面会报 500 状态码错误,视图函数不会执行。
process_exception 方法倒序执行,然后再倒序执行 process_response 方法。
返回值是 HttpResponse 对象,页面不会报错,返回状态码为 200。
视图函数不执行,该中间件后续的 process_exception 方法也不执行,直接从最后
一个中间件的 process_response 方法倒序开始执行。
若是 process_view 方法返回视图函数,提前执行了视图函数,且视图函数报错,则无论
process_exception 方法的返回值是什么,页面都会报错, 且视图函数和 process_exception 方法都不执行。
直接从最后一个中间件的 process_response 方法开始倒序执行:
'''
class MD1(MiddlewareMixin):
def process_request(self, request):
print("md1 process_request 方法。", id(request)) #在视图之前执行
def process_response(self,request, response): :#基于请求响应
print("md1 process_response 方法!", id(request)) #在视图之后
return response
def process_view(self,request, view_func, view_args, view_kwargs):
print("md1 process_view 方法!") #在视图之前执行 顺序执行
#return view_func(request)
def process_exception(self, request, exception):#引发错误 才会触发这个方法
print("md1 process_exception 方法!")
# return HttpResponse(exception) #返回错误信息
'''
process_template_response(很少用)
视图函数执行完毕之后返回的对象中含有render属性对应一个render方法
则会从下往上执行配置文件中注册了的中间件里面的process_template_response方法
'''
def index(request):
print('视图函数:index')
def render():
return HttpResponse('很奇葩')
res = HttpResponse("视图函数:index")
res.render = render
return res
'''
CSRF跨站点请求伪造
CSRF跨站点请求伪造(Cross—Site Request Forgery):大概可以理解为攻击者盗用了你的身
份,以你的名义在恶意网站发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击
者所期望的一个操作,比如以你的名义发送邮件、发消息,盗取你的账号,甚至于购买商品、转账等。
csrf解决策略
# 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 %} 之后获取数据 'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()
2.方式2:模板语法直接获取
'csrfmiddlewaretoken':{{ csrf_token }}
'''
<script>
$('#d1').click(function () {
$.ajax({
url:'',
type:'post',
data:{
'current_user':$('input[name="current_user"]').val(),
'target_user':$('input[name="target_user"]').val(),
'money':$('input[name="money"]').val(),
{#'csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()#}
{#'csrfmiddlewaretoken':{{ csrf_token }}#}
},
success:function (args) {
alert(args)
}
})
})
</script>
'''
通用方法js脚本自动处理
JS:
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
'''也只能适用于ajax提交 form表单还是需要额外指定'''