djang处理csrf_token
不同源
同源:访问的两个url使用相同协议,相同的域,以及相同的端口才是同源,否则不能算作同源。在访问一个源时,在该源中夹杂了访问另一个源的请求时候,这就是一个跨域的请求。这样的请求会带来风险。浏览器端后根据源的不同的进行数据的隔离,一个域不能获取到其他域中保存的数据 。服务器端为了保证接受的数据是客户端的正常请求,而非其他网站使用身份伪造的方式发起,需要客户在请求中的携带csrf_token,这个token值只可能由本域的请求才能构造出来,其他请求无法伪造,这就达到了请求的认证。
csrf_token验证中间件
django的csrf验证使用中间件的方式进行验证,在视图函数处理该请求前会事先验证token,可以在setting中禁用该中间件,将不会检查请求的token信息,
验证原理
django使用的验证方式是一种双cookie验证方式,使用post请求提交信息时候会触发该csrf_token的验证,在请求的头信息中需要携带两个字段信息,cookie字段中的csrftoken数据和名为"X-CSRFToken"的字段信息,该字段值为csrftoken。也就是头信息中必须包含如下的样式的信息。
headers
...
Cookies: csrftoken=FJAIOA3AJIAOG...
X-CSRFToken: FJAIOA3AJIAOG...
...
获取csrf_token值
模板中使用
django提供了模板及模板语言,使用模板时,在模板中添加{% csrf_token %
当该页面被客户端请求返回时,会在该页面会获得该token值,并在头信息的cookie中添加csrf_token值
前后端分离
token值由后端生成,前端请求使用token验证使用token验证,需要提前获取token值,必须提供一个前端获取的接口,django内置提供了装饰器方便获取该token值。
# 路由文件配置 urlpatterns = [ path("gettoken", get_csrf), ] # 响应的视图函数 from django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie # 通过get方法访问,获取一个token并返回,原理同注释方式添加token def get_csrf(request): # token = get_token(request) # get_token方法可以获取一个token值 # ret = JsonResponse({}) # ret.set_cookie("csrftoken", token) # 在返回的对象上设置该cookie # return ret return HttpResponse() # body信息中可以不返回任何值
前端访问该借口后可以获取一个token值,在返回体的头信息中会产生set-cookie字段,浏览器收到返回后将会在该域下添加该csrftoken的cookie值信息。
生成X-CSRFToken
X-CSRFToken字段值需要从cookie中获取,前提是该设置的csrf_token的cookie值是非HTTP_ONLY,才能通过前端的JS获取使用。上面的获取token的请求响应返回浏览器后,该域下的cookie值将会多一个csrftoken=""。然后通过JS提取该token值并在post请求发起时候构建X-CSRFToken
字段值,添加到请求头信息中发送至服务器端进行验证。通过JS获取token值的方式有如下两种
- 使用document全局对象直接提取,对应key的cookie值。
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 = cookies[i].trim(); // 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');
- 使用"js-cookie"包提取
- 安装js-cookies
yarn add js-cookies
- 提取cookie
import Cookie from "js-cookies" let tokenvalue = Cookie.get("csrftoken") // 根据key值提取对应的cookie值 // 使用axios发送ajax请求,自定义头信息。 import {Axios} from "axios" let config = { headers:{ url:"/api/posts" X-CSRFToken:Cookie.get("csrftoken") // 提取cookie值设置X-CSRFToken字段 } } Axios.post(config) .then( response => {}, reason => {} )
js-cookie
包还可以实现cookie的增删改查,上面实现了对cookie值的提取。