如何在Axios.interceptors.request的config中获取Cookie里的csrftoken?
解决Axios请求拦截器无法获取csrftoken的问题
先看你遇到的核心问题:document.cookie返回空、拦截器里拿不到csrftoken,而且Cookie里的csrftoken时有时无。结合你的配置,我整理了几个排查和解决方向:
1. 先确认Cookie的HttpOnly属性
如果浏览器DevTools里看到csrftoken的HttpOnly是勾选状态,那document.cookie和Cookies.get()都拿不到这个值——因为HttpOnly Cookie禁止前端JS访问。
- 检查Django的
CSRF_COOKIE_HTTPONLY设置:默认是False,如果你的settings.py里把它设成了True,就会导致这个问题。改回CSRF_COOKIE_HTTPONLY = False就能让前端拿到。
2. 跨域场景下的Cookie SameSite和域名匹配问题
你的Axios baseURL是http://10.10.10.105:8001/,如果前端页面的域名和这个不一致(比如前端是localhost:8080),属于跨域请求,这时候要确保:
- Django端设置
CSRF_COOKIE_SAMESITE = 'Lax';如果是跨域HTTPS场景,设为'None',同时开启CSRF_COOKIE_SECURE = True。 - 前端Axios的
withCredentials: true已经配置,但要确保后端CORS配置允许携带Credentials:
在Django的settings.py里,设置CORS_ALLOW_CREDENTIALS = True,并且CORS_ALLOWED_ORIGINS要明确包含前端的域名(比如http://localhost:8080),不能用通配符*,否则withCredentials会失效。
3. 利用Axios自带的XSRF自动处理,不用手动拿Cookie
其实你已经配置了xsrfCookieName: 'csrftoken'和xsrfHeaderName: 'x-csrftoken',Axios会自动帮你从Cookie里取csrftoken并加到请求头里,根本不用手动在拦截器里写代码!
- 把你拦截器里手动设置
x-csrftoken的代码删掉,Axios会自动处理,这样还能避免手动获取的问题。
4. rest_auth和allauth对CSRF的影响
rest_auth在登录等接口会自动处理CSRF,但要确保:
- 首次访问时,后端已经给前端种下csrftoken Cookie。如果前端是直接访问接口而不是通过Django的模板页面,可能需要手动触发CSRF Cookie的生成——比如先发起一个GET请求到自定义的
/api/csrf/视图(可以用Django REST Framework写一个简单视图返回CSRF token,或者调用Django自带的非csrf_exempt视图)。 - allauth的注册登录接口默认需要CSRF,确保Cookie正确种下后,Axios的自动处理就能生效。
5. 为什么Cookie里的csrftoken时有时无?
这可能是因为:
- 会话过期:csrftoken和session绑定,session过期后Cookie会被清除。
- 跨域场景下,SameSite设置导致Cookie没有被携带,前端自然看不到。
- 浏览器隐私设置:比如开启了第三方Cookie拦截,导致跨域的Cookie无法存储。
调整后的拦截器代码(去掉手动CSRF处理)
Axios.interceptors.request.use( config => { // 只处理Authorization头 if (Cookies.get('token') !== undefined) { config.headers['Authorization'] = 'Token ' + Cookies.get('token'); } return config; }, error => { return Promise.reject(error.data.error.message); } );
对应Django settings.py配置参考
# CSRF相关配置 CSRF_COOKIE_HTTPONLY = False # 允许前端JS访问CSRF Cookie CSRF_COOKIE_SAMESITE = 'Lax' # 跨域HTTPS场景改为'None',同时开启CSRF_COOKIE_SECURE = True # CORS相关配置 CORS_ALLOW_CREDENTIALS = True CORS_ALLOWED_ORIGINS = [ "http://localhost:8080", # 替换成你的前端实际域名 ]
内容的提问来源于stack exchange,提问作者user7693832
相关产品推荐
相关产品推荐

