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

React调用Django JWT认证接口出现401未授权问题咨询

Django JWT API集成React后401未授权问题解决

问题描述

用Django搭建了基于JWT的身份验证API,单独调用时:登录获取令牌后调用/api/hello/接口正常返回数据。但集成到React应用后出现问题:

  • React能正常登录,react-auth-kit也把JWT令牌存在了Cookie里
  • 但在Home.js中调用/api/hello/时,Django返回401未授权错误
  • 手动在请求头里加Authorization: Bearer <token>就能正常请求,不确定这是不是正确的实现方式

核心原因

Django默认的JWTAuthentication只从请求头的Authorization字段解析令牌,不会自动读取Cookie中的令牌。你的React应用虽然把令牌存在了Cookie,但请求时没有把令牌放到Authorization头里,导致Django无法识别用户身份,返回401。

手动加请求头是正确的实现方式吗?

是的,这是JWT身份验证的标准用法。JWT的官方推荐传递方式就是通过Authorization: Bearer <token>请求头,这种方式安全且符合行业规范。

不过可以优化实现,不用每次请求都手动写请求头,下面给出两种方案:

方案1:全局配置Axios自动添加Authorization头

给Axios设置全局请求拦截器,自动从react-auth-kit获取令牌并添加到请求头,避免重复代码。

  1. 创建Axios实例文件:
// src/utils/axiosInstance.js
import axios from 'axios';
import { getAuthToken } from 'react-auth-kit';

const axiosInstance = axios.create({
  baseURL: 'http://localhost:8000/api/',
  withCredentials: true,
});

// 请求拦截器:自动添加Authorization头
axiosInstance.interceptors.request.use(
  (config) => {
    const token = getAuthToken();
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

export default axiosInstance;
  1. 在Home.js中使用这个实例:
import { Button, Container } from "@mui/material";
import { useSignOut } from "react-auth-kit";
import { useNavigate } from "react-router-dom";
import axiosInstance from '../utils/axiosInstance';

function Home() {
  const signOut = useSignOut();
  const navigate = useNavigate();
  
  const logout = () => {
    signOut();
    navigate("login");
  };

  const getHelloWord = async () => {
    try {
      const response = await axiosInstance.get("hello/");
      console.log("Response: ", response);
    } catch (error) {
      console.log("ERROR:", error);
    }
  };

  return (
    <Container>
      <h2>HELLO WORLD</h2>
      <Button onClick={getHelloWord}>HELLO WORD</Button>
      <Button onClick={logout}>Logout</Button>
    </Container>
  );
}

export default Home;

方案2:修改Django配置,支持从Cookie读取令牌(可选)

如果不想在前端处理请求头,可以自定义Django的JWT认证类,让它同时支持从请求头和Cookie读取令牌。

  1. 自定义认证类:
# app/authentication.py
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework import exceptions

class CookieJWTAuthentication(JWTAuthentication):
    def authenticate(self, request):
        # 优先从Authorization头读取令牌
        header = self.get_header(request)
        if header is not None:
            return super().authenticate(request)
        
        # 头中没有令牌时,从Cookie读取(Cookie名要和react-auth-kit存储的一致)
        token = request.COOKIES.get('_auth')
        if not token:
            return None
        
        try:
            validated_token = self.get_validated_token(token)
            return self.get_user(validated_token), validated_token
        except exceptions.AuthenticationFailed:
            return None
  1. 修改settings.py中的认证配置:
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'app.authentication.CookieJWTAuthentication',  # 替换为自定义类
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
}
  1. 确保react-auth-kit把令牌存在指定Cookie中:
    在login.js的signIn方法中添加存储配置:
signIn({
  token: response.data.access,
  expiresIn: 600,
  tokenType: "Bearer",
  authState: { username: values.username },
  storageType: "cookie",
  cookieName: "_auth",  # 和Django中读取的Cookie名一致
  cookieDomain: window.location.hostname,
  cookieSecure: false,  # 开发环境设为false,生产环境改为true
});

总结

  • 手动添加Authorization头是标准且正确的实现方式,推荐用全局Axios拦截器简化代码
  • 从Cookie读取令牌是可选方案,适合不想在前端处理请求头的场景,但需要修改Django的认证逻辑

内容的提问来源于stack exchange,提问作者Martin Bouhier

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 17:47:03