前言:
SameSite 属性相对项目的 javax.servlet-api:3.1.0还是太新了,而项目是 Spring 的,并且 Cookie 并没有 SameSite 这个属性,那么对于新的浏览器(chrome 80 之后等)多了 SameSite 属性,比如说单点登录这种,导致没有带上 token 而用户一直登录不了,现在就得给cookie带上 SameSite。
SameSite:
防止第三方恶意 CSRF 攻击,所以用于控制第三方 Cookie,有 Strict、Lax、None 三个值,当设置为 None 时候,需要配合 Secure 使用,并且只能够 Https 访问才允许第三方发送。
增加 Maven 依赖:
加一个 redies 包的依赖,需要调用到里面的类
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>2.5.1</version>
</dependency>
增加配置类:
我之所以用 @Service,是因为项目里面没有 @Configuration 或者 @Configurable,是因为项目都用 xml 进行配置。
考虑到项目配置管理问题,要么全部 xml 或者要么全部 类配置,避免重名的 xml 和 类已经属性配置相互加载覆盖(spring 的配置加载顺序)。
import org.springframework.stereotype.Service;
import org.springframework.context.annotation.Bean;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;
@Service
public class SpringCookieConfiguration {
private static final String cookieName = "SSO_LOGIN";
@Bean
public CookieSerializer loginInCookieConfig() { // 作为单例配置
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName(cookieName); // 设置 Key
serializer.setCookieMaxAge(60 * 60 * 24);
serializer.setCookiePath("/test/");
serializer.setSameSite("NONE"); // 增加 SameSite
serializer.setUseSecureCookie(true); // 增加 Secure
return serializer;
}
}
注入配置类:
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.session.web.http.CookieSerializer;
@Service
public class LoginService {
@Autowired
private CookieSerializer l;
/**
* 设置 跨域/Https cookie
*/
public void setToken(HttpServletRequest rq, HttpServletResponse rp, String t) {
CookieSerializer.CookieValue c = new CookieSerializer.CookieValue(rq,rp, t);
l.writeCookieValue(c); // 这里已经写入了 response
}
}
后记:
看上面代码好像没写入cookie一样,这就是不看源码的人:
查看 writeCookieValue 这个方法就能看到 CookieValue 其实是封装类, response 被封了进去,然后方法内又拿了出来,最后 response 进行 addHeader(区别于 setHeader),这个方法和 response.addCookie 核心处理是相同的流程处理,并且增加了 SameSite 的属性.
此外还得注意 HttpOnly、cookieName 这些源码都是单独设置有默认值的
CookieSerializer:
Response: