google samesite属性springboot的解决方案

问题描述:

在第三方网页内嵌我司页面时,在chrome浏览器中直接访问到我司页面无法携带已登录用户信息的cookie,通过了解自chrome51开始,浏览器的cookie新增了一个samesite属性,用来方式CSRF攻击和用户追踪,如果用户登陆成功之后,未设置samesite属性,则在第三方跳转时,不会携带当前网站的cookie

CSRF攻击和用户追踪可通过文末链接1进行了解

问题分析:

在明白了为何cookie携带不上之后,然后去找我们项目中cookie是如何响应浏览器的,观看一下伪代码发现当前javax包下的cookie原生并不支持chrome的samesite属性
image.png
通过观察浏览器的属性设置发现服务器在响应浏览器时cookie的设置是通过response的header设置来进行cookie设置的,如图:
image.png
通过一顿分析之后,可以在拦截器外层通过拿到response里面的headers进行拼接,拼接上samesite的key value值即可

问题解决:

  1. 新建问题工具类
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");
        }
    }


}

  1. 在当前项目中的Filter中进行使用
filterChain.doFilter(servletRequest, response);
// 注意必须得在拦截器之后使用 即cookie添加成功之后使用
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
CookieSameSiteUtils.addSameSite(httpServletResponse);
  1. 使用环境说明

SpringBoot项目或者tomcat项目中都可使用,需要添加hutool包,因为用到了hutool包中的反射功能,或者自行修改反射相关代码
如果是tomcat项目需要添加mimeheader类等相关war包中没有的依赖

<dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.7</version>
</dependency>

参考链接:

posted @ 2022-03-31 18:02  hatricks  阅读(282)  评论(0)    收藏  举报