React+Go JWT授权问题:Cookie与localStorage不匹配如何解决?
JWT授权验证失败问题解决方案
问题核心
后端JWT中间件仅从Cookie中读取token进行验证,但前端将token存在localStorage中,通过Authorization: Bearer <token>请求头传递,导致请求无法通过验证。
方案1:前端改用Cookie自动传递(推荐,安全性更高)
后端设置的Cookie带有HttpOnly属性,前端JS无法直接读取,但浏览器会自动在同域请求中携带该Cookie。只需调整前端请求配置,确保携带凭证即可:
修改前端React请求代码
useEffect(() => { const userId = 'your_user_id_here'; // 替换为实际获取用户ID的逻辑 const fetchProfile = async () => { try { const response = await axios.get(`http://127.0.0.1:8080/api/accounts/${userId}`, { withCredentials: true // 关键:允许axios携带Cookie }); setProfileData(response.data); } catch (error) { console.error('Profile fetch error:', error.response ? error.response.data : error.message); } }; fetchProfile(); }, []);
跨域场景补充
如果前后端是跨域部署,后端还需配置CORS:
- 允许
Access-Control-Allow-Credentials: true - 明确指定允许的Origin(不能使用通配符
*)
方案2:重构后端中间件,同时支持Cookie与Bearer Token
若坚持使用localStorage存储token并通过请求头传递,可修改后端中间件,同时兼容两种token获取方式:
修改后端JWT中间件代码
import "strings" func JWTMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var tknStr string // 优先从Authorization头获取Bearer Token authHeader := r.Header.Get("Authorization") if authHeader != "" { parts := strings.Split(authHeader, " ") if len(parts) == 2 && parts[0] == "Bearer" { tknStr = parts[1] } } // 若请求头无token,则尝试从Cookie读取 if tknStr == "" { c, err := r.Cookie("token") if err != nil { if err == http.ErrNoCookie { functionalities.WriteJSON(w, http.StatusUnauthorized, APIServerError{Error: "Unauthorized"}) return } functionalities.WriteJSON(w, http.StatusBadRequest, APIServerError{Error: err.Error()}) return } tknStr = c.Value } claims := &Claims{} tkn, err := jwt.ParseWithClaims(tknStr, claims, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, http.ErrNotSupported } return []byte("SECRET"), nil }) if err != nil { if err == jwt.ErrSignatureInvalid { functionalities.WriteJSON(w, http.StatusUnauthorized, APIServerError{Error: "Unauthorized"}) return } functionalities.WriteJSON(w, http.StatusBadRequest, APIServerError{Error: err.Error()}) return } if !tkn.Valid { functionalities.WriteJSON(w, http.StatusUnauthorized, APIServerError{Error: "Unauthorized"}) return } next.ServeHTTP(w, r) }) }
配套调整登录接口
登录成功后,除了设置Cookie,还需将token返回给前端,以便存入localStorage:
// 登录接口生成token后 http.SetCookie(w, &http.Cookie{ Name: "token", Value: tokenString, Expires: time.Now().UTC().Add(time.Hour), HttpOnly: true, Secure: true, Path: "/", }) // 返回token给前端 functionalities.WriteJSON(w, http.StatusOK, map[string]string{"token": tokenString})
前端登录逻辑补充
// 登录请求示例 axios.post('/api/login', { username, password }) .then(res => { localStorage.setItem('authToken', res.data.token); });
内容的提问来源于stack exchange,提问作者srmback
相关产品推荐
相关产品推荐

