解决浏览器无法保存 Cookie 的问题

问题

在浏览器开发者工具中看到 HTTP 请求中存在响应 Cookie,但在 Cookie 列表中找不到,并且浏览器并没有阻止 Cookie。

分析过程

检查浏览器隐私设置

因为我看到响应体中是存在 Cookie 的,所以我第一个想法是“可能是浏览器阻止了 Cookie”,但是我检查过后,没有发现问题。

检查 HttpOnly 属性

检查完浏览器之后,我尝试用 JavaScript 获取 Cookie 的值,但依旧获取不到,此时我想到 HttpOnly 属性,因为 Cookie 如何设置了 HttpOnly 属性,那么就无法通过 JavaScript 获取到 Cookie 的值。

但检查过后,依旧没有解决问题。

检查 Secure 属性

设置了 Secure 属性后,就只能通过 https 链接传输,无法使用 http,虽然我没有设置该属性,但想到可能 SpringBoot 可能会默认设置该属性,于是检查,但检查之后,依旧没有解决问题。

检查 CORS 配置

解决不了问题后,最终在 AI 的帮助下,我答应了请求头和响应头的信息,经过 AI 的分析后,我了解到在设置 Cookie 时,服务器的 CORS 中的 Access-Control-Allow-Origin 的值不能设置为通配符(比如:*)。

同时,需要手动设置允许携带凭证,因为一般情况下浏览器不会在跨域请求中携带凭证,即该选项的默认值为 false

原 CORS 配置

@Configuration  
public class CorsConfig {  
    public CorsConfig() {  
    }  
    private CorsConfiguration buildConfig() {  
        CorsConfiguration corsConfiguration = new CorsConfiguration();  
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        return corsConfiguration;  
    }  

    @Bean  
    public CorsFilter corsFilter() {  
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();  
        source.registerCorsConfiguration("/**", this.buildConfig());  
        return new CorsFilter(source);  
    }  
}

修改后

@Configuration  
public class CorsConfig {  
    public CorsConfig() {  
    }  
    private CorsConfiguration buildConfig() {  
        CorsConfiguration corsConfiguration = new CorsConfiguration();  
        // 指定具体域名
        corsConfiguration.addAllowedOrigin("http://localhost:9001");  
        corsConfiguration.addAllowedHeader("*");  
        corsConfiguration.addAllowedMethod("*");  
        // 显式设置允许跨域请求携带凭证
        corsConfiguration.setAllowCredentials(true);  
        return corsConfiguration;  
    }  
  // ...
}

允许携带凭证不仅要在服务器的 CORS 中配置,还需要在前端的请求中配置。我这里使用的是 axios。

原代码

import config from "../config";
import axios from "axios";

const apiUrl = config.apiUrl;

const server = axios.create({
  baseURL: apiUrl,
  timeout: 5000
});

server.interceptors.request.use(config => {
  return config;
}, error => {
  return Promise.reject(error);
});

server.interceptors.response.use(response => {
  return response;
}, error => {
  return Promise.reject(error);
});

export default server;

修改后

import config from "../config";
import axios from "axios";

const apiUrl = config.apiUrl;

const server = axios.create({
  baseURL: apiUrl,
  timeout: 5000,
  // 手动设置允许携带凭证
  withCredentials: true
});
// ...
export default server;

而到了这一步,我的问题也已经解决,浏览器开发者工具中的 Cookie 列表也成功显示了保存的 Cookie。

总结

通过正确配置前端和后端的请求和响应设置,解决了浏览器无法保存 Cookie 的问题,确保了跨域请求能够成功发送和接收 Cookie。这些修改提高了应用的可靠性和安全性,确保用户认证和会话管理能够正常工作。

滚动至顶部