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值的方式有如下两种

  1. 使用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');
  1. 使用"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值的提取。

原文地址:https://www.cnblogs.com/k5210202/p/13080802.html