django中间件和csrf_token
django中间件
http协议
#四大特性
1. 基于请求响应
2. 基于tcp/udp协议之上
3, 无状态
4. 无/短链接
#请求格式
请求首行(http协议版本,当前请求的方式)
请求头(一大堆k,v键值对)
/r/n
请求体(存放的是一些数据,并不是每种请求方式都有请求体,get没有请求体,post有)
#响应状态码
简单的说就是用一串数字来表示一些复杂的状态或者描述性信息
1xx:
服务端已经接受到你的数据正在处理,你可以继续提交数据
2xx:
服务器端成功响应你的数据(200)
3xx:
重定向
4xx:
找不到你需要的数据或不符合获得数据的条件(403,404)
5xx:
服务器端出现故障(500)
#url:统一资源定位符:(网址)
"""
django中间件是django的门户
1.请求来的时候需要先经过中间件才能到达真正的django后端
2.响应走的时候最后也需要经过中间件才能发送出去
django自带七个中间件
"""
django请求生命周期流程图
研究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',
]
class SessionMiddleware(MiddlewareMixin):
def process_request(self, request):
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
request.session = self.SessionStore(session_key)
def process_response(self, request, response):
return response
class CsrfViewMiddleware(MiddlewareMixin):
def process_request(self, request):
csrf_token = self._get_token(request)
if csrf_token is not None:
# Use same token next time.
request.META['CSRF_COOKIE'] = csrf_token
def process_view(self, request, callback, callback_args, callback_kwargs):
return self._accept(request)
def process_response(self, request, response):
return response
class AuthenticationMiddleware(MiddlewareMixin):
def process_request(self, request):
request.user = SimpleLazyObject(lambda: get_user(request))
"""
django支持程序员自定义中间件并且暴露给程序员五个可以自定义的方法
1.必须掌握
process_request
执行顺序是中间件的注册顺序, 从上到下
process_response
执行顺序是中间件的注册倒序, 从下到上
2.了解即可
process_view
urls.py 之后, views.py之前执行, 中间件注册的顺序执行
process_template_response
返回的对象中必须要render属性才会触发
process_exception
视图有异常才会触发
"""
如何自定义中间件
1. 在项目名或引用下创建一个任意名称的文件夹
2. 在该文件夹内创建一个任意名称的py文件
3. 在py文件中书写类(这个类必须继承MiddlewareMixin)
然后就可以在这个类中定义五个方法了
4. 将类的路径以字符串的形式注册到配置文件中
五个方法
必须掌握
def process_request(self, request):
1. 请求来的时候需要经过每一个中间里面的process_request方法, 结果的顺序是按照配置文件中注册的中间价的顺序从上往下执行
2. 如果中间价里面没有定义该方法, 直接跳过执行下一个中间价
3. 如果该方法返回了HTTPResponse对象, name请求不在继续往下执行, 而是直接原路返回
process_request方法就是用来做全局相关的所有限制功能
def process_response(self, request, process):
1. 响应走的时候需要经过每一个中间价里面的process_response方法, 该方法有两个额外的参数request, response
2. 该方法必须返回一个HttpResponse对象
1. 默认返回的既是形参HttpResponse
2. 也可以返回自己自定义的
3. 顺序是按照中间件配置文件的顺序由下到上, 如果中间件没有定义该方法直接跳过执行下一个
知识点:如果第一个process_request方法就返回了HTTPResponse对象, 那么响应的时候是经过同级process_response返回
flask矿建中的中间件方法是返回的数据就必须经过所有的雷士与process_response方法
2.了解即可
process_view(self, request, view_name, *args, **kwargs)
路由匹配成功之后执行视图函数之前,会自动执行中间件里面的该方法
顺序是按照配置文件中注册的中间件从上往下的顺序依次执行
process_template_response(self, request, response)
返回的HttpResponse对象有render属性的时候才会触发
顺序是按照配置文件中注册了的中间件从下往上依次经过
process_exception(self, exception)
当视图函数中出现异常的情况下触发
顺序是按照配置文件中注册了的中间件从下往上依次经过
csrf跨站请求伪造
钓鱼网站
内部本质
我们在钓鱼网站的页面 针对对方账户 只给用户提供一个没有name属性的普通input框
然后我们在内部隐藏一个已经写好name和value的input框
如何规避上述问题
csrf跨站请求伪造校验
网站在给用户返回一个具有提交数据功能页面的时候会给这个页面加一个唯一标识
当这个页面朝后端发送post请求的时候 我的后端会先校验唯一标识,如果唯一标识不对直接拒绝(403 forbbiden)如果成功则正常执行
# form表单如何符合校验
<form action="" method="post">
{% csrf_token %}
<p>username:<input type="text" name="username"></p>
<p>target_user:<input type="text" name="target_user"></p>
<p>money:<input type="text" name="money"></p>
<input type="submit">
</form>
# ajax如何符合校验
// 第一种 利用标签查找获取页面上的随机字符串
{#data:{"username":'jason','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()},#}
// 第二种 利用模版语法提供的快捷书写
{#data:{"username":'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},#}
// 第三种 通用方式直接拷贝js代码并应用到自己的html页面上即可
data:{"username":'jason'}
csrf相关装饰器
"""
1.网站整体都不校验csrf,就单单几个视图函数需要校验
2.网站整体都校验csrf,就单单几个视图函数不校验
"""
from django.views.decorators.csrf import csrf_protect,csrf_exempt
from django.utils.decorators import method_decorator
"""
csrf_protect 需要校验
针对csrf_protect符合我们之前所学的装饰器的三种玩法
csrf_exempt 忽视校验
针对csrf_exempt只能给dispatch方法加才有效
"""
# @csrf_exempt
# @csrf_protect
def transfer(request):
if request.method == 'POST':
username = request.POST.get('username')
target_user = request.POST.get('target_user')
money = request.POST.get('money')
print('%s给%s转了%s元'%(username,target_user,money))
return render(request,'transfer.html')
from django.views import View
# @method_decorator(csrf_protect,name='post') # 针对csrf_protect 第二种方式可以
# @method_decorator(csrf_exempt,name='post') # 针对csrf_exempt 第二种方式不可以
@method_decorator(csrf_exempt,name='dispatch')
class MyCsrfToken(View):
# @method_decorator(csrf_protect) # 针对csrf_protect 第三种方式可以
# @method_decorator(csrf_exempt) # 针对csrf_exempt 第三种方式可以
def dispatch(self, request, *args, **kwargs):
return super(MyCsrfToken, self).dispatch(request,*args,**kwargs)
def get(self,request):
return HttpResponse('get')
# @method_decorator(csrf_protect) # 针对csrf_protect 第一种方式可以
# @method_decorator(csrf_exempt) # 针对csrf_exempt 第一种方式不可以
def post(self,request):
return HttpResponse('post')
importlib模块
可以将''xxx.yy''通过importlib.import_module()方法装换成form xxx import yy
最多只能到py文件名
重要思想
import settings
import importlib
def send_all(content):
for path_str in settings.NOTIFY_LIST: #'notify.email.Email'
module_path,class_name = path_str.rsplit('.',maxsplit=1)
# module_path = 'notify.email' class_name = 'Email'
# 1 利用字符串导入模块
module = importlib.import_module(module_path) # from notify import email
# 2 利用反射获取类名
cls = getattr(module,class_name) # Email、QQ、Wechat
# 3 生成类的对象
obj = cls()
# 4 利用鸭子类型直接调用send方法
obj.send(content)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律