You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Django REST Framework与django-rest-knox实现HttpOnly Cookie存储认证令牌后,如何通过React和Axios访问受保护路由

解决HttpOnly Cookie下React + Axios访问DRF受保护路由的问题

嘿,你其实已经走对了关键一步——用HttpOnly Cookie存token是非常安全的做法!这里的核心点是:HttpOnly Cookie会被浏览器自动附加到同域(或符合CORS配置的跨域)请求中,根本不需要你手动通过JavaScript获取token再塞到Authorization头里。下面一步步帮你搞定整个流程:

1. 后端先搞定CORS和Token认证适配

首先要确保后端允许前端携带凭证(Cookie),并且能从Cookie里读取knox的token进行验证:

配置CORS(用django-cors-headers)

如果还没装,先安装django-cors-headers,然后在settings.py里做如下配置:

INSTALLED_APPS = [
    # ... 其他app
    'corsheaders',
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',  # 要放在CommonMiddleware前面
    'django.middleware.common.CommonMiddleware',
    # ... 其他中间件
]

# 允许携带Cookie
CORS_ALLOW_CREDENTIALS = True
# 允许你的前端域名(开发环境是localhost:3000,生产环境换成实际域名)
CORS_ALLOWED_ORIGINS = [
    "http://localhost:3000",
]

自定义Token认证类(从Cookie取token)

knox默认是从Authorization头取token,现在我们要改成从Cookie读取。在你的app下新建authentication.py:

from rest_framework.exceptions import AuthenticationFailed
from knox.auth import TokenAuthentication

class CookieTokenAuthentication(TokenAuthentication):
    def authenticate(self, request):
        # 从Cookie中获取我们存的auth_token
        token = request.COOKIES.get('auth_token')
        if not token:
            return None
        
        # 复用knox的token验证逻辑
        try:
            return self.authenticate_credentials(token)
        except AuthenticationFailed:
            return None

然后在settings.py里把这个认证类设为默认,或者在单个视图里指定:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'your_app_name.authentication.CookieTokenAuthentication',
        # 可以保留原来的TokenAuthentication,兼容两种认证方式
        'knox.auth.TokenAuthentication',
    ],
}

2. 前端Axios配置(自动携带Cookie)

只需要给Axios设置withCredentials: true,浏览器就会自动把HttpOnly Cookie附加到请求里了。建议创建一个全局Axios实例:

在src/utils/axios.js里:

import axios from 'axios';

const axiosInstance = axios.create({
  baseURL: 'http://localhost:8000/api/',  // 替换成你的API base地址
  withCredentials: true,  // 关键!开启后浏览器自动携带Cookie
});

// 针对POST/PUT/DELETE等修改请求,需要带上CSRF Token(Django默认开启CSRF保护)
axiosInstance.interceptors.request.use((config) => {
  // 从可访问的csrftoken Cookie中取值
  const csrfToken = document.cookie.split('; ')
    .find(row => row.startsWith('csrftoken='))?.split('=')[1];
  if (csrfToken) {
    config.headers['X-CSRFToken'] = csrfToken;
  }
  return config;
});

export default axiosInstance;

之后在组件里直接用这个实例请求受保护路由就行:

import axiosInstance from '../utils/axios';

const fetchProtectedData = async () => {
  try {
    const response = await axiosInstance.get('/protected-endpoint/');
    console.log('受保护数据:', response.data);
  } catch (error) {
    console.error('请求失败:', error);
    // 处理未认证情况,比如跳回登录页
    if (error.response.status === 401) {
      window.location.href = '/login';
    }
  }
};

几个额外注意点

  • SameSite设置:你代码里已经设了samesite='strict',这是最安全的配置,适合前后端同域的场景;如果是跨域场景,可能需要调整为'lax',但优先保持strict。
  • 登出逻辑:登出时要后端清除Cookie,比如在knox的登出视图里添加response.delete_cookie('auth_token')。
  • 生产环境配置:要确保前后端都使用HTTPS,Cookie加上secure=True,进一步提升安全性。

内容的提问来源于stack exchange,提问作者Fady's Cube

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 09:32:45