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); } } }
主要疑问
- Postman确认向
http://localhost:8080/collaborator/login发送POST请求时收到两个JWT Token,但我并未为http://localhost:8080/collaborator/路径设置Cookie+JWT,为何会收到该路径的Token? - 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
相关产品推荐
相关产品推荐

