Django自带的CSRF保护是一个是十分棒的插件。在使用Django开发的过程中,它仅仅只需要你引入一行代码,就可以保护你的表单不受CSRF攻击的困扰。
但在开发Api时,它会困扰着许多程序员,接下来我们分两个情况来解决它(都是基于你在使用 Cookies 进行身份验证的时候,不是用 Cookies 也就没有 CSRF 防护的需要了,直接删掉 Django 中对应的中间件即可)。
同源请求
对于同源网站而言,这十分好解决。在Django里有两个设置,分别是
-
CSRF_COOKIE_NAME,用于指定Cookies中存放CSRF token值的名称,默认是csrftoken;
-
CSRF_HEADER_NAME,用于指定从请求头中读取CSRF token的头部名称,默认是HTTP_X_CSRFTOKEN,翻译到实际的头名称应该是——X-CSRFTOKEN。
你只需要使用JS读取Cookies当中的CSRF token,在发送请求时附带对应的头部信息即可。如果你使用的是axios之类的较为完善的库,你甚至都不需要手动读Cookies,只需要增加对应的options即可。以axios为例:
const ap = axios.create({
xsrfHeaderName: 'X-CSRFToken',
xsrfCookieName: 'csrftoken',
})
当然,也可以通过修改 Django 的配置来适应 axios 的默认值,axios 的默认值如下所示。
// `xsrfCookieName` is the name of the cookie to use as a value for xsrf token
xsrfCookieName: 'XSRF-TOKEN', // default
// `xsrfHeaderName` is the name of the http header that carries the xsrf token value
xsrfHeaderName: 'X-XSRF-TOKEN', // default
跨域请求
对于跨域请求,需要绕过HTTP Referer报头的限制,我们配置起来也很容易。例如我需要upload.abersheeran.com能够跨域请求到api.abersheeran.com,只需要在api的项目配置里增加
CSRF_TRUSTED_ORIGINS = [
'upload.abersheeran.com',
]
如果是想允许abersheeran.com下所有子域名都被允许,那么可以配置为
CSRF_TRUSTED_ORIGINS = [
'.abersheeran.com',
]
然后再使用同源请求的方法进行访问即可。