资讯详情

加入spring sesion redis后,cookie无法跨域请求

springsecurity spring session redis

项目使用springsecurity进行认证和鉴权

因为项目每次部署登陆都会失败(session 认证机制)

故集成spring session redis将session保存在redis当中

集成完成后,发现认证成功后返回session-id登录后携带session-id不同导致认证成功

问题在于集成spring session redis 返回响应头 set-cookie上

此时SameSite的值为Lax,cookie部门场景不允许跨域

SameSite 属性

Cookie 的SameSite该属性用于限制第三方 Cookie,从而降低安全风险。

它可以设置三个值。

  • Strict
  • Lax
  • None

1 Strict

Strict第三方完全禁止最严格的 Cookie,任何情况下任何情况下都不会发送 Cookie。换句话说,只有当前的网页 URL 只有与请求目标一致,才会带上 Cookie。

Set-Cookie: CookieName=CookieValue; SameSite=Strict; 

这一规则过于严格,可能会导致非常糟糕的用户体验。例如,当前的网页有一个 GitHub 链接,用户点击跳转 GitHub 的 Cookie,跳转过去总是没有登。

2 Lax

Lax规则略有放宽,大多数情况下不发送第三方 Cookie,但导航到目标网站 Get 请求除外。

Set-Cookie: CookieName=CookieValue; SameSite=Lax; 

导航到目标网站 GET 只有三种情况:链接,预加载请求,GET 表单。详见下表。

请求类型 示例 正常情况 Lax
链接 <a href="..."></a> 发送 Cookie 发送 Cookie
预加载 <link rel="prerender" href="..."/> 发送 Cookie 发送 Cookie
GET 表单 <form method="GET" action="..."> 发送 Cookie 发送 Cookie
POST 表单 <form method="POST" action="..."> 发送 Cookie 不发送
iframe <iframe src="..."></iframe> 发送 Cookie 不发送
AJAX $.get("...") 发送 Cookie 不发送
Image <img src="..."> 发送 Cookie 不发送

设置了StrictLax以后基本杜绝了 CSRF 攻击。当然,前提是用户浏览器支持 SameSite 属性。

3 None

Chrome 计划将Lax变成默认设置。此时,网站可以选择显式关闭。SameSite属性,设置为None。但前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。

参考博文:Cookie 的 SameSite 属性

问题的原因及解决方案

1.当我们介绍它时spring session redis的依赖包spring-session-core包括时间session自动配置

@Bean         @Conditional({SessionAutoConfiguration.DefaultCookieSerializerCondition.class})         DefaultCookieSerializer cookieSerializer(ServerProperties serverProperties, ObjectProvider<DefaultCookieSerializerCustomizer> cookieSerializerCustomizers) {             Cookie cookie = serverProperties.getServlet().getSession().getCookie();             DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();             PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();             cookie.getClass();             map.from(cookie::getName).to(cookieSerializer::setCookieName);             cookie.getClass();             map.from(cookie::getDomain).to(cookieSerializer::setDomainName);             cookie.getClass();             map.from(cookie::getPath).to(cookieSerializer::setCookiePath);             cookie.getClass();             map.from(cookie::getHttpOnly).to(cookieSerializer::setUseHttpOnlyCookie);             cookie.getClass();             map.from(cookie::getSecure).to(cookieSerializer::setUseSecureCookie);             cookie.getClass();             map.from(cookie::getMaxAge).to((maxAge) -> {                 cookieSerializer.setCookieMaxAge((int)maxAge.getSeconds());             });             cookieSerializerCustomizers.orderedStream().forEach((customizer) -> {                 customizer.customize(cookieSerializer);             });             return cookieSerializer;         }

上述代码从配置文件中读取cookie的用户自定义配置(一般是在application.yml中定义的) 然后新建了cookie序列化配置类 用户定义的参数通过PropertyMapper工具设置到cookie序列化配置类(有兴趣可以阅读)PropertyMapper源码,还是比较容易读懂的)

注入遍历mvc环境的cookieSerializerCustomizers调用接口法 void customize(DefaultCookieSerializer cookieSerializer)

注入DefaultCookieSerializer

2  注解分析 @Conditional({SessionAutoConfiguration.DefaultCookieSerializerCondition.class})

上述注释是条件注入的注释,DefaultCookieSerializerConditin继承了AnyNestedCondition,当DefaultCookieSerializerCondition中分段注解任一生效时,bean就会注入

DefaultCookieSerializerCondition具体代码如下:

static class DefaultCookieSerializerCondition extends AnyNestedCondition {
        DefaultCookieSerializerCondition() {
            super(ConfigurationPhase.REGISTER_BEAN);
        }

        @ConditionalOnBean({CookieHttpSessionIdResolver.class})
        @ConditionalOnMissingBean({CookieSerializer.class})
        static class CookieHttpSessionIdResolverAvailable {
            CookieHttpSessionIdResolverAvailable() {
            }
        }

        @ConditionalOnMissingBean({HttpSessionIdResolver.class, CookieSerializer.class})
        static class NoComponentsAvailable {
            NoComponentsAvailable() {
            }
        }
    }

3.再溯源到DefaultCookieSerializer类中,找到罪魁元首

4.解决方案

手写配置注入CookieSerializer

@Configuration
public class SpringSessionConfig {
    @Bean
    DefaultCookieSerializer cookieSerializer(ServerProperties serverProperties, ObjectProvider<DefaultCookieSerializerCustomizer> cookieSerializerCustomizers) {
        Session.Cookie cookie = serverProperties.getServlet().getSession().getCookie();
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setSameSite(null);
        PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
        map.from(cookie::getName).to(cookieSerializer::setCookieName);
        map.from(cookie::getDomain).to(cookieSerializer::setDomainName);
        map.from(cookie::getPath).to(cookieSerializer::setCookiePath);
        map.from(cookie::getHttpOnly).to(cookieSerializer::setUseHttpOnlyCookie);
        map.from(cookie::getSecure).to(cookieSerializer::setUseSecureCookie);
        map.from(cookie::getMaxAge).to((maxAge) -> {
            cookieSerializer.setCookieMaxAge((int)maxAge.getSeconds());
        });
        cookieSerializerCustomizers.orderedStream().forEach((customizer) -> {
            customizer.customize(cookieSerializer);
        });
        return cookieSerializer;
    }

}

问题解决:

标签: sames电阻仪ap1000

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台