在SvelteKit中通过外部Golang API设置JWT Cookie失败的问题
问题描述
在SvelteKit应用中调用外部Golang API完成登录并设置JWT Cookie,代码执行无报错,但浏览器中始终看不到设置的Cookie。想确认是否无法通过外部API设置JWT Cookie?由于大部分业务逻辑都在该外部API中,希望通过它完成认证流程。
SvelteKit 前端代码
async function OnSubmit() { //test let res = await fetch('http://localhost:50000/login', { credentials: 'same-origin', method: 'POST', mode: 'cors', body: JSON.stringify({ Username: 'raka', Password: 'password1' }) }); console.log('🚀 ~ file: index@blank.svelte ~ line 45 ~ OnSubmit ~ res', res); if (res.ok) { console.log('🚀 ~ file: index.svelte ~ line 49 ~ OnSubmit ~ value : ', 200); } }
Golang 后端API代码
func main() { http.HandleFunc("/login", handler.Login) http.HandleFunc("/home", handler.Home) http.HandleFunc("/", handler.Home2) http.HandleFunc("/refresh", handler.Refresh) fmt.Println("listening in port 50000") log.Fatal(http.ListenAndServe(":50000", nil)) } func Login(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Headers", "Content-Type") fmt.Println("Login is hit ...") var credentials Credentials err := json.NewDecoder(r.Body).Decode(&credentials) if err != nil { w.WriteHeader(http.StatusBadRequest) return } expectedPassword, ok := Users[credentials.Username] if !ok || expectedPassword != credentials.Password { w.WriteHeader(http.StatusUnauthorized) return } expirationTime := time.Now().Add(time.Minute * 5) claims := &Claims{ Username: credentials.Username, StandardClaims: jwt.StandardClaims{ ExpiresAt: expirationTime.Unix(), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString(jwtKey) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } http.SetCookie(w, &http.Cookie{ Name: "token", Value: tokenString, Expires: expirationTime, }) }
问题原因及解决方案
不是不能通过外部API设置Cookie,而是你的跨域(CORS)配置和请求参数存在问题,导致浏览器拒绝存储Cookie:
1. CORS 配置错误
当Access-Control-Allow-Origin设为*时,浏览器会禁止携带credentials(包括Cookie),这是安全限制。必须将其改为前端的具体域名(比如SvelteKit默认的http://localhost:5173),同时添加Access-Control-Allow-Credentials: true头,允许跨域携带凭证。
2. Fetch 请求的 credentials 参数错误
当前设置的credentials: 'same-origin'只在同域请求时生效,跨域场景下需要改为credentials: 'include',这样浏览器才会在请求中携带Cookie,并且接收服务器返回的Cookie。
3. Cookie 属性缺失
建议给Cookie添加HttpOnly(防止XSS攻击窃取Cookie)、SameSite(控制跨站Cookie发送规则,可选Lax/Strict,如果是HTTPS环境可以用None但必须配合Secure)属性,提升安全性同时避免浏览器拦截。
修改后的代码示例
调整后的Golang Login接口
func Login(w http.ResponseWriter, r *http.Request) { // 替换成你的SvelteKit前端实际地址 w.Header().Set("Access-Control-Allow-Origin", "http://localhost:5173") w.Header().Set("Access-Control-Allow-Headers", "Content-Type") // 允许跨域携带凭证 w.Header().Set("Access-Control-Allow-Credentials", "true") fmt.Println("Login is hit ...") var credentials Credentials err := json.NewDecoder(r.Body).Decode(&credentials) if err != nil { w.WriteHeader(http.StatusBadRequest) return } expectedPassword, ok := Users[credentials.Username] if !ok || expectedPassword != credentials.Password { w.WriteHeader(http.StatusUnauthorized) return } expirationTime := time.Now().Add(time.Minute * 5) claims := &Claims{ Username: credentials.Username, StandardClaims: jwt.StandardClaims{ ExpiresAt: expirationTime.Unix(), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenString, err := token.SignedString(jwtKey) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } http.SetCookie(w, &http.Cookie{ Name: "token", Value: tokenString, Expires: expirationTime, HttpOnly: true, // 禁止JS读取,防范XSS攻击 SameSite: http.SameSiteLaxMode, // 兼容大多数业务场景 Path: "/", // 让Cookie在所有路径下生效 // 如果是HTTPS部署环境,添加以下配置 // Secure: true, }) }
调整后的SvelteKit Fetch代码
async function OnSubmit() { let res = await fetch('http://localhost:50000/login', { credentials: 'include', // 跨域时允许携带并接收Cookie method: 'POST', mode: 'cors', headers: { 'Content-Type': 'application/json', // 显式设置请求内容类型 }, body: JSON.stringify({ Username: 'raka', Password: 'password1' }) }); console.log('🚀 ~ OnSubmit ~ res', res); if (res.ok) { console.log('登录成功'); } }
额外说明
- 如果前端和后端部署在不同域名下,
Access-Control-Allow-Origin必须设置为前端的实际域名,不能使用* - 如果使用
SameSite: None,必须同时设置Secure: true,且网站必须采用HTTPS协议,否则浏览器会拒绝存储Cookie
内容的提问来源于stack exchange,提问作者sk shahriar ahmed raka
相关产品推荐
相关产品推荐

