【中间件:django自带7个中间件】
django中间件是django的门户
1.请求来的时候需要先经过中间件才能到达正真的django后端,
2.响应走的时候最后也需要经过中间件才能发送出去
SessionMiddleware中间件源码分析 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
CsrfViewMiddleware中间件源码分析 class CsrfViewMiddleware(MiddlewareMixin): def process_request(self, request): csrf_secret = self._get_secret(request) if csrf_secret is not None: request.META["CSRF_COOKIE"] = csrf_secret def process_view(self, request, callback, callback_args, callback_kwargs): return self._accept(request) def process_response(self, request, response): return response
AuthenticationMiddleware中间件源码分析 class AuthenticationMiddleware(MiddlewareMixin): def process_request(self, request): if not hasattr(request, "session"): raise ImproperlyConfigured( "The Django authentication middleware requires session " "middleware to be installed. Edit your MIDDLEWARE setting to " "insert " "'django.contrib.sessions.middleware.SessionMiddleware' before " "'django.contrib.auth.middleware.AuthenticationMiddleware'." ) request.user = SimpleLazyObject(lambda: get_user(request))
总结:
'''
django自带7个中间件,里面都继承了一个MiddlewareMixin类,里面都有一个def process_request、def process_view、def process_response方法
django还支持自定义中间件,并且暴露给程序员五个自定义的方法:
1.必须掌握的
process_request 请求进来时,权限认证
process_response 请求有响应式执行
2.了解
process_view 路由匹配之后,能够得到视图函数
process_template_response 模板渲染时执行
process_exception 异常时执行
'''
。
。
。
【自定义中间件】
(process_response方法)
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse # 自定义中间件类 class MyMiddleware1(MiddlewareMixin): def process_request(self, request): print('我是自定义中间件里面的process_request方法') # return HttpResponse('我是第一个自定义中间件里面的process_request方法返回值') # 如果该方法返回了HttpResponse对象,则不会继续向下执行, def process_response(self, request, response): ''' :param request: :param response: 就是dajango后端返回给浏览器的内容 :return: ''' print('我是自定义中间件里面的process_response方法') return HttpResponse('看看返回我自己写的返回值') # 不返回会报错 class MyMiddleware2(MiddlewareMixin): def process_request(self, request): print('我是第二个自定义中间件里面的process_request方法') ''' 总结: 请求来的时候需要经过每一个中间件里面的process_request方法 结果的顺序是按照配置文件中注册的中间件从上往下的顺序依次执行 2.如果中间件里面没有定义process_request方法,则不会执行,跳过去执行下一个中间件 3.如果中间件里面返回了HttpResponse对象,则不会继续向下执行, process_response方法就是用来做全局相关的所有限制功能 ''' def process_response(self, request, response): print('我是第二个自定义中间件里面的process_response方法') return response ''' 总结: 执行顺序:响应来的时候先执行process_request方法,响应走的时候执行process_response方法是倒着返回的 该方法有两个额外的参数request和response,request就是请求对象,response就是响应对象 2.该方法必须返回一个HttpResponse对象,默认返回的就是response,也可以是返回自己的 3.如果第一次process_request方法就遇见了返回HttpResponse对象, 只会返回第一次自定义中间件里的response和request方法,不会继续向下执行, ps:flask框架中也有一个中间件,但是它的规律是: 只要返回数据了就必须经过所有中间件里面的类似于process_response方法 '''
。
。
。
【csrf】
### csrf跨站请求伪造(就是钓鱼网站)
Cross-site request forgery 跨站请求伪造
钓鱼网站:模仿一个正规的网站,让用户在该网站上做操作,但是操作的结果会影响到用户正常的网站账户,但是其中有一些猫腻。
eg:英语四六级考试需要网上先缴费,但是你会发现卡里的钱扣了,但是却交到了一个莫名其妙的账户,并不是真正的四六级官方账户
--------------------------------------
在假网站的转账页面上输入用户名与密码后,假网站会拿这这些数据朝真网站服务端发送请求,假如你用户名密码输对了,真网站就会正常给你扣钱了,但是假网站却从中把转账的收款人改掉了,应该转给官方账户的结果转给了陌生账户去了!!! 然后你会发现,你的钱也扣了,也是真网站做的处理,但是收款人却不对了,这就是钓鱼网站
钓鱼网站套路就是:先做一个假网站,再做一个和真网站一摸一样的页面,用户在这个假页面上操作的请求也是发给真网站,只不过在发给真网站的过程中,假网站把其中某些重要的数据做了修改,比如把转账的收款人改掉,或者转账的金额改掉等等!!用户的账户信息是存在真网站的,所以肯定要朝真网站发送请求!!
--------------------------------------
模拟钓鱼网站案例:转账案例
内部隐藏标签
(day70真正的网站)
(70模拟钓鱼网站)
造成这种现象的原因实际上就一点:真网站区分不出来,朝它发请求的到底真网站发过来的,还是从钓鱼网站发过来的!!!因为钓鱼网站的页面也能朝真网站的后台发送请求!!!
而且这时候还要注释掉配置文件里的'django.middleware.csrf.CsrfViewMiddleware',
.
.
.
csrf校验策略
真网站在给用户发送一些比较核心的页面时,比如说这个页面是转账页面这种比较重要的页面的时候,在发给用户的时候会在页面上添加一个唯一标识!然后等页面朝后端发请求的时候,后端会先校验页面有没有这个标识,如果没有,说明这个页面根本不是原来后端给的页面,有问题,直接拒绝掉请求。
这样假网站搞出的假网页携带数据朝真网站发送请求时,真网站一看页面上没有标识,或者标识是错的,立刻就知道不是一个正常的请求!!!从而把假网站的请求给拒绝掉!!!
可以看到{% csrf_token %}模板语法会在页面上自动生成一个input标签,标签的name=csrfmiddlewaretoken value=是一个随机生成的字符串这就是唯一的标识,每刷新一次,这个串都会变,永远都是独一无二的,同一个网址连续请求,每次唯一标识的串都会变,这样就保证了时效性了,一个串只能用一次,用完就失效了。
也就是说比如登录页面,当输入网址或跳转网址进入登录页面时,中间件会给登录页面添加一个唯一标识,只有带该唯一标识的登录页面提交post请求时,中间件检查标识没有问题才能让请求的数据往后面走!!也就是说要中间件先给串,再提交请求的时候再拿着给的串作为凭证,才能通过中间件的校验。
假网址的网页是不可能有正网站中间件给的唯一标识的串的,所以提交post请求数据,在csrf中间这一定过不了!!!请求一定会被csrf中间件拒绝掉的!!!
【form表单与ajax 针对csrf 的策略】
// 方式3:直接引入一个js脚本即可(官网提供的),以后会经常用到 参考:https://www.cnblogs.com/Dominic-Ji/p/9234099.html 在静态文件的static文件夹里面新建一个js文件比如叫myjs.js,然后把如下代码粘贴进去,在html页面上通过导入该文件( <script src="/static/myjs.js"></script> )即可自动帮我们解决ajax提交post数据时校验csrf_token的问题,(导入该配置文件之前,需要先导入jQuery,因为这个配置文件内的内容是基于jQuery来实现的) 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); } } });
。
。
。
【csrf相关装饰器】
# 模拟转账,crsf # FBV添加装饰器的方式 from django.views.decorators.csrf import csrf_exempt, csrf_protect
总结: ''' csrf_exempt, 忽视校验 只能加给dispatch方法才能生效 不需要注释掉CsrfViewMiddleware csrf_protect 需要校验: 针对csrf_protect符合我们之前所学的装饰器的三种玩法 注释掉CsrfViewMiddleware ''' # @csrf_exempt # CsrfViewMiddleware不注释掉,前端 {% csrf_token %}注释掉,显示不校验 # @csrf_protect # 注释掉CsrfViewMiddleware,提交数据过后,显示报错 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') # CBV校验 from django.views import View from django.utils.decorators import method_decorator # @method_decorator(csrf_protect, name='post') # 第二种也可以 # @method_decorator(csrf_exempt, name='post') # 第二种不可以忽视校验 class MyCsrfToken(View): # @method_decorator(csrf_protect) # 第三种也需要校验 @method_decorator(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) # 不可以忽视校验 def post(self, request): return HttpResponse('post')
。
。
。
【importlib模块:字符串的导入获取文件名】
。
。
。
【django中间件的补充】
需求:发送通知,一发送通知,同时发往各个员工的邮箱,微信,QQ
(分开写法)