如何在csrftoken
的配置中获取Cookie Axios.interceptors.request
?
Axios.interceptors.request.use(
config => {
if (
config.method === "post" ||
config.method === "put" ||
config.method === "delete"||
config.method === "get"
) {
}
if (Cookies.get('token')!==undefined) {
config.headers['Authorization']= 'Token '+Cookies.get('token');
}
// there I try to get the `csrftoken` in the Cookies, but I can not get.
if (Cookies.get('csrftoken')!==undefined) {
config.headers['x-csrftoken']= Cookies.get('csrftoken'); // 'CSRFToken'
}
return config;
},
error => {
return Promise.reject(error.data.error.message);
}
);
在Axios.interceptors.request
的配置中,我无法获取Cookie csrftoken
:Cookies.get('csrftoken')
。
我的AxiosConfig代码如下:
AxiosConfig:{
baseURL: 'http://10.10.10.105:8001/',
responseType: "json",
withCredentials: true, // there will send the Cookie (with it there are: sessionid, csrftoken)
xsrfCookieName: 'csrftoken', // default: XSRF-TOKEN
xsrfHeaderName: 'x-csrftoken', // default: X-XSRF-TOKEN
headers: {
"Content-Type": "application/json;charset=utf-8"
}
}
修改-1
Cookie中有csrftoken
。
修改-2
在Cookie中,也没有csrftoken
。
修改-3
如果我在控制台中获得document.cookie
,我将获得""
:
```
的document.cookie
< “” ```
修改-4
在我的Django后端,settings.py
:
INSTALLED_APPS:
...
'corsheaders',
'rest_framework',
'rest_framework.authtoken',
'rest_framework_docs',
'rest_auth',
'allauth',
'allauth.account',
'allauth.socialaccount',
'rest_auth.registration',
...
我不确定rest_auth
和allauth
是否会影响csrftoken
。
答案 0 :(得分:1)
首先,请务必确保Cookie未标记为httpOnly。
如果是,您的javascript
代码将无法读取/修改其内容。
您可以在浏览器中查看Cookie标签,看看它是否可读。
在您的情况下,django
不应将标记设置为httpOnly
,因为docs描述了如何直接从javascript
读取值饼干。
我可以通过经验指出一些事情:
config.headers = ...;
可能会触发错误。 请务必写下:
config.headers = config.headers || {};
在设置headers
之前,所以没有' config.headers未定义' 将被触发。
csrf
值存储在隐藏的input
中。您可以执行以下操作(语法可能不正确):
<input type="hidden"
name="csrftoken"
value="{% csrf_token %}"/>
</div>
然后在拦截器中发送令牌:
config.headers['x-csrftoken'] = document.querySelector('input[name="csrftoken"]').value;
在这种情况下,由于您不需要阅读Cookie,因此将其设置为httpOnly
将是巨大的优势。
答案 1 :(得分:0)
Axios具有order of precedence来配置设置,因此设置可能被其他代码覆盖。
例如,在 Chrome 浏览器中,您可以打开“开发工具”窗格,单击“应用程序”选项卡,然后在左侧单击“ Cookie”以查看这些以确保正确存在:
如果您有一个定义request interceptor
头的Axios XSRF-TOKEN
,它将被以下内容覆盖:
axios.post(route('logout'), undefined, {
headers: {
'XSRF-TOKEN': 'bad',
},
});
如果您有一个文件,例如在许多Laravel / Vue项目中称为bootstrap.js
或axios.js
的文件,它声明了全局配置设置,则该设置可能会被拦截器覆盖。
例如:
// document head
<meta name="csrf-token" content="{{ csrf_token() }}">
...
// axios.js or bootstrap.js (imported in SPA app's main.js file)
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
const token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
// an interceptor would overwrite this due to right-to-left precedence
window.axios.defaults.headers.common['XSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
最后一个示例非常重要,因为它将用于调用内部API。如果您要调用利用CORS的外部API(例如Google),则它们可能需要特定的标头,而其他标头可能会引发错误。
要临时覆盖标头,可以在调用外部API的地方使用这种模式:
// temporarily wipe 'XSRF-TOKEN' header for Google CORS
const instance = axios.create();
instance.defaults.headers.common = {};
instance.defaults.headers.common.accept = 'application/json';
const { data } = await instance.get('https://www.external.com/foobars');
这也会覆盖拦截器,因为设计上的instance
优先于全局默认值。
这是我使用的request interceptor
:
import Cookies from 'js-cookie';
/**
* Request interceptor: for each request to the server,
* attach the CSRF token if it exists.
*
*/
axios.interceptors.request.use(async (request) => {
try {
const csrf = Cookies.get('XSRF-TOKEN');
request.withCredentials = true;
if (csrf) {
request.headers.common['XSRF-TOKEN'] = csrf;
}
return request;
} catch (err) {
throw new Error(`axios# Problem with request during pre-flight phase: ${err}.`);
}
});
由于CSRF要求可以通过JavaScript进行访问,因此必须不能为httpOnly
,因此您可以使用{ {1}},但返回以分号分隔的键/值对字符串,因此您可以通过创建提取CSRF的函数来锻炼头脑。
js-cookie
奖金阅读: