google samesite属性springboot的解决方案
问题描述:
在第三方网页内嵌我司页面时,在chrome浏览器中直接访问到我司页面无法携带已登录用户信息的cookie,通过了解自chrome51开始,浏览器的cookie新增了一个samesite属性,用来方式CSRF攻击和用户追踪,如果用户登陆成功之后,未设置samesite属性,则在第三方跳转时,不会携带当前网站的cookie
CSRF攻击和用户追踪可通过文末链接1进行了解
问题分析:
在明白了为何cookie携带不上之后,然后去找我们项目中cookie是如何响应浏览器的,观看一下伪代码发现当前javax包下的cookie原生并不支持chrome的samesite属性
通过观察浏览器的属性设置发现服务器在响应浏览器时cookie的设置是通过response的header设置来进行cookie设置的,如图:
通过一顿分析之后,可以在拦截器外层通过拿到response里面的headers进行拼接,拼接上samesite的key value值即可
问题解决:
- 新建问题工具类
package com.chinasofti.broker.bpm.common.filter;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.http.Header;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.http.MimeHeaders;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.util.HashSet;
import java.util.Set;
/**
* @packageName: com.chinasofti.broker.bpm.common.filter
* @className: CookieSameSiteUtils
* @author: hatricks
* @date: 2022/3/31 17:46
* @description:
*/
@Slf4j
public class CookieSameSiteUtils {
public static void addSameSite(HttpServletResponse response) {
MimeHeaders mimeHeaders = getMimeHeaders(response);
if (mimeHeaders == null) {
log.info("获取不到响应中的header");
return;
}
Set<String> cookieValues = new HashSet<>();
for (int i = 0, size = mimeHeaders.size(); i < size; i++) {
if (mimeHeaders.getName(i).equalsIgnoreCase(Header.SET_COOKIE.getValue())) {
cookieValues.add(mimeHeaders.getValue(i).getString().concat(";SameSite=").concat("None"));
}
}
mimeHeaders.removeHeader(Header.SET_COOKIE.getValue());
for (String messageByte : cookieValues) {
MessageBytes messageBytes = mimeHeaders.addValue(Header.SET_COOKIE.getValue());
messageBytes.setString(messageByte);
}
}
private static MimeHeaders getMimeHeaders(ServletResponse response) {
Object res = getResponse(response);
if (res != null) {
return (MimeHeaders) ReflectUtil.getFieldValue(res, "headers");
}
return null;
}
private static Object getResponse(Object obj) {
Object res = ReflectUtil.getFieldValue(obj, "response");
if (res != null) {
return getResponse(res);
} else {
return ReflectUtil.getFieldValue(obj, "coyoteResponse");
}
}
}
- 在当前项目中的Filter中进行使用
filterChain.doFilter(servletRequest, response);
// 注意必须得在拦截器之后使用 即cookie添加成功之后使用
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
CookieSameSiteUtils.addSameSite(httpServletResponse);
- 使用环境说明
SpringBoot项目或者tomcat项目中都可使用,需要添加hutool包,因为用到了hutool包中的反射功能,或者自行修改反射相关代码
如果是tomcat项目需要添加mimeheader类等相关war包中没有的依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.7</version>
</dependency>
参考链接:
本文来自博客园,作者:hatricks,转载请注明原文链接:https://www.cnblogs.com/hatricks/articles/16083104.html

浙公网安备 33010602011771号