django
1. django的session原理流程
2. django 中间件
1. 中间件简介
"""
django中间件是django的门户
1.请求来的时候需要先经过中间件才能到达真正的django后端
2.响应走的时候最后也需要经过中间件才能发送出去
django自带七个中间件
"""
django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。
在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件
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 :
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
process_template_response
process_exception
"""
2. 自定义中间件
自定义步骤:
- 写一个类,继承MiddlewareMixin
- 里面写方法process_request(请求来了,一定会触发它的执行)
- 在setting中配置( 注意,放在前和放在后)
MIDDLEWARE = [
. . .
'app01.mymiddle.MyMiddleware1' ,
. . .
]
"""
1. 在项目名或者应用名下创建一个任意名称的文件夹
2. 在该文件夹内创建一个任意名称的py文件
3. 在该py文件内需要书写类(这个类必须继承MiddlewareMixin)
然后在这个类里面就可以自定义五个方法了
(这五个方法并不是全部都需要书写,用几个写几个)
4. 需要将类的路径以字符串的形式注册到配置文件中才能生效
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',
'你自己写的中间件的路径3',
]
"""
1 . process_request
1 . 请求来的时候需要经过每一个中间件里面的process_request方法
结果的顺序是按照配置文件中注册的中间件从上往下的顺序依次执行
2 . 如果中间件里面没有定义该方法,那么直接跳过执行下一个中间件
3 . 如果该方法返回了HttpResponse对象,那么请求将不再继续往后执行
而是直接原路返回( 校验失败不允许访问. . . )
process_request方法就是用来做全局相关的所有限制功能
2 . process_response
1 . 响应走的时候需要结果每一个中间件里面的process_response方法
该方法有两个额外的参数request, response
2 . 该方法必须返回一个HttpResponse对象
3 . 默认返回的就是形参response
4 . 你也可以自己返回自己的
5 . 顺序是按照配置文件中注册了的中间件从下往上依次经过
3 . process_view
路由匹配成功之后执行视图函数之前会自动执行 ( callback就是视图函数)
顺序是按照配置文件中注册的中间件从上往下的顺序依次执行
def process_view ( self, request, callback, callback_args, callback_kwargs) :
print ( callback)
print ( callback_args)
print ( callback_kwargs)
res= callback( request)
print ( "中间件的process_view" )
return res
4 . process_template_response
返回的HttpResponse对象有render属性的时候才会触发
顺序是按照配置文件中注册了的中间件从下往上依次经过
5 . process_exception
当视图函数中出现异常的情况下触发 ( 全局异常捕获)
顺序是按照配置文件中注册了的中间件从下往上依次经过
应用场景: 记录日志,哪个ip地址,访问哪个路径,出现异常
def process_exception ( self, request, exception) :
print ( exception)
return render( request, 'error.html' )
如果在第一个process_request方法就已经返回了HttpResponse对象,那么响应走的时候会直接走同级别的process_reponse返回
请求来的时候从上往下执行: process_request
请求走的时候从下往上执行: process_response
写一个中间件,不管前端用什么编码,在requset. data中都有post的数据
频率限制(限制某个ip地址,一分钟只能访问5 次)
登录认证(只要没登录,重定向到login路径)、
记录用户访问日志(ip,时间,访问路径)
统一给所有(某几个路径)加cookie
统一给所有(某几个路径)加响应头
3. CSRF_TOKEN跨站请求伪造
1. 示例
我搭建一个跟正规网站一模一样的界面( 中国银行)
用户不小心进入到了我们的网站,用户给某个人打钱
打钱的操作确确实实是提交给了中国银行的系统,用户的钱也确确实实减少了
但是唯一不同的时候打钱的账户不适用户想要打的账户变成了一个莫名其妙的账户
考之前需要学生自己网站登陆缴费
我们在钓鱼网站的页面 针对对方账户 只给用户提供一个没有name属性的普通input 框
然后我们在内部隐藏一个已经写好name和value的input 框
csrf跨站请求伪造校验
网站在给用户返回一个具有提交数据功能页面的时候会给这个页面加一个唯一标识
当这个页面朝后端发送post请求的时候 我的后端会先校验唯一标识
如果唯一标识不对直接拒绝( 403 forbbiden) 如果成功则正常执行
2. csrf_token校验
中间件:django. middleware. csrf. CsrfViewMiddleware
用户每次发送post请求,都需要携带csrf_token随机字符串
form表单提交
在form表单中 { % csrf_token % }
< 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( {
url: '/csrf_test/' ,
method: 'post' ,
data: { 'name' : $( '[name="name"]' ) . val( ) ,
'password' : $( '[name="password"]' ) . val( ) ,
'csrfmiddlewaretoken' : $( '[name="csrfmiddlewaretoken"]' ) . val( )
} ,
success: function ( data) {
console. log( '成功了' )
console. log( data)
} ,
error: function ( data) {
console. log( 'xxxxx' )
console. log( data)
}
} )
data: { "username" : 'jason' , 'csrfmiddlewaretoken' : '{{ csrf_token }}' } ,
headers: { 'X-CSRFToken' : '{{ csrf_token }}' } ,
3. 代码演示
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) ;
}
}
} ) ;
4. csrf装饰器
1 . 网站整体都不校验csrf 就单单几个视图函数需要校验
@csrf_protect 需要校验
2 . 网站整体都校验csrf 就单单几个视图函数不校验
@csrf_exempt 忽视校验
from django. views. decorators. csrf import csrf_exempt, csrf_protect
from django. utils. decorators import method_decorator
@csrf_exempt
def csrf_test ( request) :
if request. method== 'GET' :
return render( request, 'csrf_test.html' )
else :
name= request. POST. get( 'name' )
password= request. POST. get( 'password' )
print ( name)
print ( password)
return HttpResponse( '登录成功' )
@csrf_protect
def csrf_test ( request) :
if request. method== 'GET' :
return render( request, 'csrf_test.html' )
else :
name= request. POST. get( 'name' )
password= request. POST. get( 'password' )
print ( name)
print ( password)
return HttpResponse( '登录成功' )
path( 'csrf_test/' , csrf_exempt( views. csrf_test) )
@method_decorator( csrf_protect, 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)
def post ( self, request) :
return HttpResponse( 'post' )
4. 模块 importlib
import importlib
res = 'myfile.b'
ret = importlib. import_module( res) <= > from myfile import b
def send_all ( content) :
for path_str in settings. NOTIFY_LIST:
module_path, class_name = path_str. rsplit( '.' , maxsplit= 1 )
module = importlib. import_module( module_path)
cls = getattr ( module, class_name)
obj = cls( )
obj. send( content)