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

SpringBoot+React登录JWT Cookie异常及500/409错误排查求助

问题描述

我是SpringBoot和ReactJS新手,恳请谅解我的不足。我原本期望向localhost:8080/collaborator/login发送POST登录请求后,JWT Token会存储在Cookie中,但实际情况如下:

  • 使用Postman测试时,收到来自localhost:8080/collaborator/和localhost:8080/collaborator/login两个路径的JWT Token,同时IntelliJ控制台报500错误:"Could not write JSON: getOutputStream() has already been called for this response]";
  • 使用ReactJS时触发AxiosError,Postman返回500,但npm启动后前端得到409错误。

我查阅了相关Stack Overflow帖子,推测可能是单次请求中重复生成了JWT Token(不解为何此操作非法),但无法定位第二次生成的位置。

后端登录代码

@CrossOrigin(origins = "*")
@RestController
@RequestMapping("collaborator")
public class UserController {
    private UserService userService;
    private JwtGeneratorInterface jwtGenerator;
    @Autowired
    public UserController(UserService userService, JwtGeneratorInterface jwtGenerator){
        this.userService=userService;
        this.jwtGenerator=jwtGenerator;
    }

    @PostMapping("/login")
    public ResponseEntity<?> loginUser(@RequestBody @NotNull User user, HttpServletResponse response) {
        try {
            if(user.getUserName() == null || user.getPassword() == null) {
                throw new UserNotFoundException("UserName or Password is Empty");
            }
            User userData = userService.getUserByNameAndPassword(user.getUserName(), user.getPassword());

            if(userData == null){
                throw new UserNotFoundException("UserName or Password is Invalid");
            }

            // Add jwtToken as a cookie in the response
            Cookie cookie = new Cookie("jwtToken", jwtGenerator.generateToken(user).get("jwtToken"));
            cookie.setHttpOnly(true);
            cookie.setMaxAge(3600); //an hour
            cookie.setPath("/collaborator/login");
            response.addCookie(cookie);

            return new ResponseEntity<>(response, HttpStatus.OK);

        } catch (UserNotFoundException e) {
            return new ResponseEntity<>(e.getMessage(), HttpStatus.CONFLICT);
        }
    }
}

主要疑问

  1. Postman确认向http://localhost:8080/collaborator/login发送POST请求时收到两个JWT Token,但我并未为http://localhost:8080/collaborator/路径设置Cookie+JWT,为何会收到该路径的Token?
  2. Postman返回500错误,但npm启动后前端得到409错误,我怀疑是前端代码问题,相关代码如下:

AuthContext.js

const AuthContext = createContext();

//this paragraph is cheesy
export const AuthContextProvider = ({ children }) => {
    const [user, setUser] = useState(() => {
    const jwtCookie = document.cookie
        .split("; ")
        .find((cookie) => cookie.startsWith("jwt")); //in Java, I use "jwtToken"
  
    if (jwtCookie) {
        const jwt = jwtCookie.split("=")[1];
        return jwt_decode(jwt);
      }
      return null;
    });


//CONFUSION
//wait, is it reasonable to send cookie using "post" back to server? 
    const navigate = useNavigate();

    const login = async (payload) => {
      const apiResponse = await axios.post(
        "http://localhost:8080/collaborator/login",payload
    );

    // Set the JWT token in a cookie instead of local storage
    document.cookie = `jwt=${apiResponse.data.access_token}`;
    setUser(jwt_decode(apiResponse.data.access_token));
    navigate("/");
    };

    const logout = async () => {
    // Remove the JWT token from the cookie, the cookie is expired because the date is past.
    document.cookie = "jwtToken=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
  
    setUser(null);
    navigate("/");
    };


  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

Login.jsx

import { useContext, useRef } from "react";
import { Col, Container, Row } from "react-bootstrap";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import AuthContext from "../components/shared/AuthContext";

const Login = () => {
  const userName = useRef("");
  const password = useRef("");
  const {login}= useContext(AuthContext);

  //I think this is where it goes wrong. 
  const loginSubmit = async () => {
    let payload = {
      username: userName.current.value,
      password: userName.current.value
    }
    await login(payload);
  };
};

jwtInterceptor.js

import axios from "axios";
import Cookies from "js-cookie";

const jwtInterceptor = axios.create({});

jwtInterceptor.interceptors.request.use((config) => {
  let jwtToken = Cookies.get("jwtToken");
  config.headers.common["Authorization"] = `Bearer ${jwtToken}`;
  return config;
});

jwtInterceptor.interceptors.response.use(
  (response) => {
    return response;
  },
  async (error) => {
    if (error.response.status === 401) {
      const jwtToken = Cookies.get("jwtToken");
      const payload = {
        access_token: jwtToken,
        refresh_token: "", // Assuming no refresh token in cookies
      };

      let apiResponse = await axios.post(
        "http://localhost:8080/collaborator/login",payload
      );

      Cookies.set("jwtToken", apiResponse.data.access_token);
      error.config.headers["Authorization"] = `Bearer ${apiResponse.data.access_token}`;
      return axios(error.config);
    } else {
      return Promise.reject(error);
    }
  }
);

export default jwtInterceptor;

内容的提问来源于stack exchange,提问作者Tsai Hsuan Hsieh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 08:42:04