springboot+ngnix的跨域session不一致问题

问题描述

  • 前后端分离页面,Vue+springboot均配置跨域,并访问成功,session取值正常。
  • ngnix代理项目,Vue访问遇到session不一致的问题,session取值为null(使用springSession进行分布式session共享)。

仅在springboot配置跨域

  • 访问springboot直接部署的项目(session取值正常)
    在这里插入图片描述

  • 访问ngnix代理的项目(session取值为null)
    在这里插入图片描述

在springboot和ngnix均配置跨域

在这里插入图片描述

  • 提示跨域配置重复。

仅在ngnix配置跨域

在这里插入图片描述

  • 提示跨域失败。此时考虑是ngnix跨域配置问题

  • 更改ngnix跨域配置

# 指定允许跨域的方法,*代表所有
add_header Access-Control-Allow-Methods *;
# 预检命令的缓存,如果不缓存每次会发送两次请求
add_header Access-Control-Max-Age 3600;
# 带cookie请求需要加上这个字段,并设置为true
add_header Access-Control-Allow-Credentials true;
# 表示允许这个域跨域调用(客户端发送请求的域名和端口) 
# $http_origin动态获取请求客户端请求的域 不用*的原因是带cookie的请求不支持*号
add_header Access-Control-Allow-Origin $http_origin;
# 表示请求头的字段 动态获取
add_header Access-Control-Allow-Headers 
$http_access_control_request_headers;
# OPTIONS预检命令,预检命令通过时才发送请求
# 检查请求的类型是不是预检命令
if ($request_method = OPTIONS){
  return 200;
}
  • 此时跨域配置成功,但sessionId仍不一致,取值为null。
    在这里插入图片描述

是因为withCredentials设置为true,Origin不能为*?

  • 测试后发现,即使Origin不为*,sessionId同样不一致。

猜想为cookie的samesite的问题

在这里插入图片描述

前后端分离–跨域问题–Cookie SameSite(一)

  • 通过查阅此文:使用springSession解决分布式session共享问题时,cookie新增了 SameSite这个字段,所以不能携带cookie进行跨域post访问。
    服务端返回给客户端的set-cookie中带有samesite=lax,这就是问题的根源,它表示不能携带cookie进行跨域post访问,然而我们是需要携带cookie的。

解决办法

  • 配置bean取消cookie的samesite设置。
@Bean
public CookieSerializer httpSessionIdResolver() {
    DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
    // 取消仅限同一站点设置
    cookieSerializer.setSameSite(null);
    return cookieSerializer;
}

在这里插入图片描述

  • 至此,sessionId一致,取值成功。

总结

  • 使用ngnix代理项目时,跨域配置springboot和ngnix只用配置任意一方,都配的话会报错。
  • springboot配置推荐使用实现filter的方式(可避免origin为*的问题)
@Component
public class MyCrosFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            HttpServletResponse httpResponse = (HttpServletResponse) response;

            // 预检请求,请求头Origin是客户端地址,要求跨域头不能是*
            String origin = httpRequest.getHeader("Origin");
            if (origin == null) {
                httpResponse.addHeader("Access-Control-Allow-Origin", "*");
            } else {
                httpResponse.addHeader("Access-Control-Allow-Origin", origin);
            }
            httpResponse.addHeader("Access-Control-Allow-Headers",
                    "Origin, x-requested-with, Content-Type, Accept,X-Cookie,token");
//httpResponse.addHeader("Access-Control-Expose-Headers", "token");

            httpResponse.addHeader("Access-Control-Allow-Credentials", "true");
            httpResponse.addHeader("Access-Control-Allow-Methods", "GET,POST,PUT,OPTIONS,DELETE");
            //预检请求,直接通过。
            if (httpRequest.getMethod().equals("OPTIONS")) {
                httpResponse.setStatus(HttpServletResponse.SC_OK);
                return;
            }
            chain.doFilter(request, response);
        } catch (Exception e) {
            throw e;
        }
    }

    @Override
    public void destroy() {
    }
}
  • ngnix的跨域配置见上文。

  • 跨域成功但是sessionId不一致的情况,查看响应头中的set-cookie是否设置了samesite,如果有,则配置bean取消cookie的samesite设置,配置方式见上文。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值