如何为JSESSIONID cookie设置SameSite和Secure属性。

huangapple go评论82阅读模式
英文:

How to set SameSite and Secure attribute to JSESSIONID cookie

问题

我有一个Spring Boot Web应用程序(Spring Boot版本2.0.3.RELEASE),在Apache Tomcat 8.5.5服务器上运行。

根据Google Chrome最近实施的安全策略(自80.0版本开始推出),要求在跨站点cookie访问时应用新的SameSite属性,以更安全的方式进行,而不是使用CSRF。由于我没有做任何相关的操作,Chrome已将默认值SameSite=Lax应用于第一方Cookie。由于其中一个第三方服务集成失败,原因是当SameSite=Lax时,Chrome限制了对跨站点cookie的访问,而且如果第三方响应来自POST请求(一旦流程完成,第三方服务会通过POST请求将控制权重定向到我们的站点)。在这种情况下,Tomcat无法找到会话,因此它在URL末尾附加一个新的JSESSIONID(具有新会话,并且之前的会话被终止)。因此,Spring拒绝了URL,因为它包含了一个分号,这个分号是由新的JSESSIONID附加引入的。

因此,我需要更改JSESSIONID cookie的属性(SameSite=None; Secure),并尝试了多种方法,包括使用WebFilters。我在Stackoverflow上看到了相同的问题和答案,并尝试了其中的大部分,但都没有解决。

请问有人能提出在Spring Boot中更改这些标头的解决方案吗?

英文:

I have a Spring Boot Web Application (Spring boot version 2.0.3.RELEASE) and running in an Apache Tomcat 8.5.5 server.

With the recent security policy which has imposed by Google Chrome (Rolled out since 80.0), it is requested to apply the new SameSite attribute to make the Cross-site cookie access in a more secure way instead of the CSRF. As I have done nothing related that and Chrome has set default value SameSite=Lax for the first-party cookies, one of my third-party service integration is failing due to the reason that chrome is restricting access of cross-site cookies when SameSite=Lax and if the third party response is coming from a POST request (Once the procedure completes third-party service redirect to our site with a POST request). in there Tomcat unable to find the session so it appends a new JSESSIONID (with a new session and the previous session was killed) at the end of the URL. So Spring rejects the URL as it contains a semicolon which was introduced by the new JSESSIONID append.

So I need to change the JSESSIONID cookie attributes(SameSite=None; Secure) and tried it in several ways including WebFilters.I have seen the same question and answers in Stackoverflow and tried most of them but ended up in nowhere.

can someone come up with a solution to change those headers in Spring Boot, please?

答案1

得分: 9


UPDATE on 06/07/2021 - Added correct Path attribute with new sameSite attributes to avoid session cookie duplication with GenericFilterBean approach.


I was able to come up with my own solution for this.

I have two kinds of applications which run on Spring boot which has different Spring security configurations and they needed different solutions to fix this.

CASE 1: No user authentication

Solution 1

In here you might have created an endpoint for the 3rd party response, in your application. You are safe until you access httpSession in a controller method. If you are accessing session in different controller method then send a temporary redirect request to there like follows.

@Controller
public class ThirdPartyResponseController{

@RequestMapping(value=3rd_party_response_URL, method=RequestMethod.POST)
public void thirdPartyresponse(HttpServletRequest request, HttpServletResponse httpServletResponse){
// your logic
// and you can set any data as an session attribute which you want to access over the 2nd controller
request.getSession().setAttribute()
try {
httpServletResponse.sendRedirect(<redirect_URL>);
} catch (IOException e) {
// handle error
}
}

@RequestMapping(value=redirect_URL, method=RequestMethod.GET)
public String thirdPartyresponse(HttpServletRequest request, HttpServletResponse httpServletResponse, Model model, RedirectAttributes redirectAttributes, HttpSession session){
// your logic
return <to_view>;
}
}

Still, you need to allow the 3rd_party_response_url in your security configuration.

Solution 2

You can try the same GenericFilterBean approach described below.

Case 2: Users need to be authenticated/sign in

In a Spring Web application where you have configured most of your security rules either through HttpSecurity or WebSecurity, check this solution.

Sample security config which I have tested the solution:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.
      ......
      ..antMatchers(<3rd_party_response_URL>).permitAll();
      ......
      ..csrf().ignoringAntMatchers(<3rd_party_response_URL>);
}

}

The Important points which I want to highlight in this configuration are you should allow the 3rd party response URL from Spring Security and CSRF protection(if it's enabled).

Then we need to create a HttpServletRequest Filter by extending GenericFilterBean class (Filter class did not work for me) and setting the SameSite Attributes to the JSESSIONID cookie by intercepting each HttpServletRequest and setting the response headers.

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class SessionCookieFilter extends GenericFilterBean {

private final List<String> PATHS_TO_IGNORE_SETTING_SAMESITE = Arrays.asList("resources", <add other paths you want to exclude>);
private final String SESSION_COOKIE_NAME = "JSESSIONID";
private final String SESSION_PATH_ATTRIBUTE = ";Path=";
private final String ROOT_CONTEXT = "/";
private final String SAME_SITE_ATTRIBUTE_VALUES = ";HttpOnly;Secure;SameSite=None";

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;
    String requestUrl = req.getRequestURL().toString();
    boolean isResourceRequest = requestUrl != null ? StringUtils.isNoneBlank(PATHS_TO_IGNORE_SETTING_SAMESITE.stream().filter(s -> requestUrl.contains(s)).findFirst().orElse(null)) : null;
    if (!isResourceRequest) {
        Cookie[] cookies = ((HttpServletRequest) request).getCookies();
        if (cookies != null && cookies.length > 0) {
            List<Cookie> cookieList = Arrays.asList(cookies);
            Cookie sessionCookie = cookieList.stream().filter(cookie -> SESSION_COOKIE_NAME.equals(cookie.getName())).findFirst().orElse(null);
            if (sessionCookie != null) {
                String contextPath = request.getServletContext() != null && StringUtils.isNotBlank(request.getServletContext().getContextPath()) ? request.getServletContext().getContextPath() : ROOT_CONTEXT;
                resp.setHeader(HttpHeaders.SET_COOKIE, sessionCookie.getName() + "=" + sessionCookie.getValue() + SESSION_PATH_ATTRIBUTE + contextPath + SAME_SITE_ATTRIBUTE_VALUES);
            }
        }
    }
    chain.doFilter(request, response);
}

}

Then add this filter to the Spring Security filter chain by

@Override
protected void configure(HttpSecurity http) throws Exception {
http.
....
.addFilterAfter(new SessionCookieFilter(), BasicAuthenticationFilter.class);
}

in order to determine where you need to place the new filter in Spring’s security filter chain, you can debug the Spring security filter chain easily and identify a proper location in the filter chain. Apart from the BasicAuthenticationFilter, after the SecurityContextPersistanceFilter would be an another ideal place.

This SameSite cookie attribute will not support some old browser versions and in that case, check the browser and avoid setting SameSite in incompatible clients.

private static final String I_PHONE_IOS_12 = "iPhone OS 12";
private static final String I_PAD_IOS_12 = "iPad; CPU OS 12";
private static final String MAC_OS_10_14 = " OS X 10_14";
private static final String _VERSION = "Version/";
private static final String _SAFARI = "Safari";
private static final String _EMBED_SAFARI = "(KHTML, like Gecko)";
private static final String _CHROME = "Chrome/";
private static final String _CHROMIUM = "Chromium/";
private static final String _UC_BROWSER = "UCBrowser/";
private static final String _ANDROID = "Android";

/*
 * checks SameSite=None;Secure incompatible Browsers
 * https://www.chromium.org/updates/same-site/incompatible-clients
 */
public static boolean isSameSiteInCompatibleClient(HttpServletRequest request) {
    String userAgent = request.getHeader("user-agent");
    if (StringUtils.isNotBlank(userAgent)) {
        boolean isIos12 = isIos12(userAgent), isMacOs1014 = isMacOs1014(userAgent), isChromeChromium51To66 = isChromeChromium51To66(userAgent), isUcBrowser = isUcBrowser(userAgent);
        //TODO : Added for testing purpose. remove before Prod release.
        LOG.info("*********************************************************************************");
        LOG.info("is iOS 12 = {}, is MacOs 10.14 = {}, is Chrome
英文:

UPDATE on 06/07/2021 - Added correct Path attribute with new sameSite attributes to avoid session cookie duplication with GenericFilterBean approach.


I was able to come up with my own solution for this.

I have two kinds of applications which run on Spring boot which has different Spring security configurations and they needed different solutions to fix this.

CASE 1: No user authentication

Solution 1

In here you might have created an endpoint for the 3rd party response, in your application. You are safe until you access httpSession in a controller method. If you are accessing session in different controller method then send a temporary redirect request to there like follows.

@Controller
public class ThirdPartyResponseController{

@RequestMapping(value=3rd_party_response_URL, method=RequestMethod.POST)
public void thirdPartyresponse(HttpServletRequest request, HttpServletResponse httpServletResponse){
    // your logic
    // and you can set any data as an session attribute which you want to access over the 2nd controller 
    request.getSession().setAttribute(&lt;data&gt;)
    try {
        httpServletResponse.sendRedirect(&lt;redirect_URL&gt;);
    } catch (IOException e) {
        // handle error
    }
}

@RequestMapping(value=redirect_URL, method=RequestMethod.GET)
public String thirdPartyresponse(HttpServletRequest request,  HttpServletResponse httpServletResponse, Model model,  RedirectAttributes redirectAttributes, HttpSession session){
    // your logic
        return &lt;to_view&gt;;
    }
}

Still, you need to allow the 3rd_party_response_url in your security configuration.

Solution 2

You can try the same GenericFilterBean approach described below.

Case 2: Users need to be authenticated/sign in

In a Spring Web application where you have configured most of your security rules either through HttpSecurity or WebSecurity, check this solution.

Sample security config which I have tested the solution:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
          ......
          ..antMatchers(&lt;3rd_party_response_URL&gt;).permitAll();
          .....
          ..csrf().ignoringAntMatchers(&lt;3rd_party_response_URL&gt;);
    }
}

The Important points which I want to highlight in this configuration are you should allow the 3rd party response URL from Spring Security and CSRF protection(if it's enabled).

Then we need to create a HttpServletRequest Filter by extending GenericFilterBean class (Filter class did not work for me) and setting the SameSite Attributes to the JSESSIONID cookie by intercepting each HttpServletRequest and setting the response headers.

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class SessionCookieFilter extends GenericFilterBean {

    private final List&lt;String&gt; PATHS_TO_IGNORE_SETTING_SAMESITE = Arrays.asList(&quot;resources&quot;, &lt;add other paths you want to exclude&gt;);
    private final String SESSION_COOKIE_NAME = &quot;JSESSIONID&quot;;
    private final String SESSION_PATH_ATTRIBUTE = &quot;;Path=&quot;;
    private final String ROOT_CONTEXT = &quot;/&quot;;
    private final String SAME_SITE_ATTRIBUTE_VALUES = &quot;;HttpOnly;Secure;SameSite=None&quot;;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        String requestUrl = req.getRequestURL().toString();
        boolean isResourceRequest = requestUrl != null ? StringUtils.isNoneBlank(PATHS_TO_IGNORE_SETTING_SAMESITE.stream().filter(s -&gt; requestUrl.contains(s)).findFirst().orElse(null)) : null;
        if (!isResourceRequest) {
            Cookie[] cookies = ((HttpServletRequest) request).getCookies();
            if (cookies != null &amp;&amp; cookies.length &gt; 0) {
                List&lt;Cookie&gt; cookieList = Arrays.asList(cookies);
                Cookie sessionCookie = cookieList.stream().filter(cookie -&gt; SESSION_COOKIE_NAME.equals(cookie.getName())).findFirst().orElse(null);
                if (sessionCookie != null) {
                    String contextPath = request.getServletContext() != null &amp;&amp; StringUtils.isNotBlank(request.getServletContext().getContextPath()) ? request.getServletContext().getContextPath() : ROOT_CONTEXT;
                    resp.setHeader(HttpHeaders.SET_COOKIE, sessionCookie.getName() + &quot;=&quot; + sessionCookie.getValue() + SESSION_PATH_ATTRIBUTE + contextPath + SAME_SITE_ATTRIBUTE_VALUES);
                }
            }
        }
        chain.doFilter(request, response);
    }
}

Then add this filter to the Spring Security filter chain by

@Override
protected void configure(HttpSecurity http) throws Exception {
        http.
           ....
           .addFilterAfter(new SessionCookieFilter(), BasicAuthenticationFilter.class);
}

in order to determine where you need to place the new filter in Spring’s security filter chain, you can debug the Spring security filter chain easily and identify a proper location in the filter chain. Apart from the BasicAuthenticationFilter, after the SecurityContextPersistanceFilter would be an another ideal place.

This SameSite cookie attribute will not support some old browser versions and in that case, check the browser and avoid setting SameSite in incompatible clients.

private static final String _I_PHONE_IOS_12 = &quot;iPhone OS 12_&quot;;
    private static final String _I_PAD_IOS_12 = &quot;iPad; CPU OS 12_&quot;;
    private static final String _MAC_OS_10_14 = &quot; OS X 10_14_&quot;;
    private static final String _VERSION = &quot;Version/&quot;;
    private static final String _SAFARI = &quot;Safari&quot;;
    private static final String _EMBED_SAFARI = &quot;(KHTML, like Gecko)&quot;;
    private static final String _CHROME = &quot;Chrome/&quot;;
    private static final String _CHROMIUM = &quot;Chromium/&quot;;
    private static final String _UC_BROWSER = &quot;UCBrowser/&quot;;
    private static final String _ANDROID = &quot;Android&quot;;

    /*
     * checks SameSite=None;Secure incompatible Browsers
     * https://www.chromium.org/updates/same-site/incompatible-clients
     */
    public static boolean isSameSiteInCompatibleClient(HttpServletRequest request) {
        String userAgent = request.getHeader(&quot;user-agent&quot;);
        if (StringUtils.isNotBlank(userAgent)) {
            boolean isIos12 = isIos12(userAgent), isMacOs1014 = isMacOs1014(userAgent), isChromeChromium51To66 = isChromeChromium51To66(userAgent), isUcBrowser = isUcBrowser(userAgent);
            //TODO : Added for testing purpose. remove before Prod release.
            LOG.info(&quot;*********************************************************************************&quot;);
            LOG.info(&quot;is iOS 12 = {}, is MacOs 10.14 = {}, is Chrome 51-66 = {}, is Android UC Browser = {}&quot;, isIos12, isMacOs1014, isChromeChromium51To66, isUcBrowser);
            LOG.info(&quot;*********************************************************************************&quot;);
            return isIos12 || isMacOs1014 || isChromeChromium51To66 || isUcBrowser;
        }
        return false;
    }

    private static boolean isIos12(String userAgent) {
        return StringUtils.contains(userAgent, _I_PHONE_IOS_12) || StringUtils.contains(userAgent, _I_PAD_IOS_12);
    }

    private static boolean isMacOs1014(String userAgent) {
        return StringUtils.contains(userAgent, _MAC_OS_10_14)
            &amp;&amp; ((StringUtils.contains(userAgent, _VERSION) &amp;&amp; StringUtils.contains(userAgent, _SAFARI))  //Safari on MacOS 10.14
            || StringUtils.contains(userAgent, _EMBED_SAFARI)); // Embedded browser on MacOS 10.14
    }

    private static boolean isChromeChromium51To66(String userAgent) {
        boolean isChrome = StringUtils.contains(userAgent, _CHROME), isChromium = StringUtils.contains(userAgent, _CHROMIUM);
        if (isChrome || isChromium) {
            int version = isChrome ? Integer.valueOf(StringUtils.substringAfter(userAgent, _CHROME).substring(0, 2))
                : Integer.valueOf(StringUtils.substringAfter(userAgent, _CHROMIUM).substring(0, 2));
            return ((version &gt;= 51) &amp;&amp; (version &lt;= 66));    //Chrome or Chromium V51-66
        }
        return false;
    }

    private static boolean isUcBrowser(String userAgent) {
        if (StringUtils.contains(userAgent, _UC_BROWSER) &amp;&amp; StringUtils.contains(userAgent, _ANDROID)) {
            String[] version = StringUtils.splitByWholeSeparator(StringUtils.substringAfter(userAgent, _UC_BROWSER).substring(0, 7), &quot;.&quot;);
            int major = Integer.valueOf(version[0]), minor = Integer.valueOf(version[1]), build = Integer.valueOf(version[2]);
            return ((major != 0) &amp;&amp; ((major &lt; 12) || (major == 12 &amp;&amp; (minor &lt; 13)) || (major == 12 &amp;&amp; minor == 13 &amp;&amp; (build &lt; 2)))); //UC browser below v12.13.2 in android
        }
        return false;
    }

Add above check in SessionCookieFilter like follows,

if (!isResourceRequest &amp;&amp; !UserAgentUtils.isSameSiteInCompatibleClient(req)) {

This filter won't work in localhost environments as it requires a Secured(HTTPS) connection to set Secure cookie attribute.

For a detailed explanation read this blog post.

答案2

得分: 3

我之前也遇到过类似的情况。由于`javax.servlet.http.Cookie`类中没有类似于`SameSite`的东西,所以无法直接添加。

**Part 1:** 所以我编写了一个过滤器,只拦截所需的第三方请求。

    public class CustomFilter implements Filter {
    
        private static final String THIRD_PARTY_URI = "/third/party/uri";
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;
            if(THIRD_PARTY_URI.equals(request.getRequestURI())) {
                chain.doFilter(request, new CustomHttpServletResponseWrapper(response));
            } else {
                chain.doFilter(request, response);
            }
        }
        
        // ... 初始化和销毁方法
        
    }

**Part 2:** Cookie 以 `Set-Cookie` 响应头的形式发送。因此,`CustomHttpServletResponseWrapper` 重写了 `addCookie` 方法,并且检查是否是所需的 cookie(`JSESSIONID`),如果是,就不将其添加到 cookie 中,而是直接添加到带有 `SameSite=None` 属性的响应头 `Set-Cookie` 中。

    public class CustomHttpServletResponseWrapper extends HttpServletResponseWrapper {

        public CustomHttpServletResponseWrapper(HttpServletResponse response) {
            super(response);
        }

        @Override
        public void addCookie(Cookie cookie) {
            if ("JSESSIONID".equals(cookie.getName())) {
                super.addHeader("Set-Cookie", getCookieValue(cookie));
            } else {
                super.addCookie(cookie);
            }
        }

        private String getCookieValue(Cookie cookie) {
            StringBuilder builder = new StringBuilder();
            builder.append(cookie.getName()).append('=').append(cookie.getValue());
            builder.append(";Path=").append(cookie.getPath());
            if (cookie.isHttpOnly()) {
                builder.append(";HttpOnly");
            }
            if (cookie.getSecure()) {
                builder.append(";Secure");
            }
            // 这里您可以添加其他属性,如 domain / max-age 等。
            builder.append(";SameSite=None");
            return builder.toString();
        }
    }
英文:

I was in same situation earlier. Since there is nothing like SameSite in javax.servlet.http.Cookie class so it's not possible to add that.

Part 1: So what I did is wrote a filter which intercepts the required third party request only.

public class CustomFilter implements Filter {

    private static final String THIRD_PARTY_URI = &quot;/third/party/uri&quot;;


    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        if(THIRD_PARTY_URI.equals(request.getRequestURI())) {
            chain.doFilter(request, new CustomHttpServletResponseWrapper(response));
        } else {
            chain.doFilter(request, response);
        }
    }
enter code here
    // ... init destroy methods here
    
}

Part 2: Cookies are sent as Set-Cookie response header. So this CustomHttpServletResponseWrapper overrides the addCookie method and check, if it is the required cookie (JSESSIONID), instead of adding it to cookie, it adds directly to response header Set-Cookie with SameSite=None attribute.

public class CustomHttpServletResponseWrapper extends HttpServletResponseWrapper {

    public CustomHttpServletResponseWrapper(HttpServletResponse response) {
        super(response);
    }

    @Override
    public void addCookie(Cookie cookie) {
        if (&quot;JSESSIONID&quot;.equals(cookie.getName())) {
            super.addHeader(&quot;Set-Cookie&quot;, getCookieValue(cookie));
        } else {
            super.addCookie(cookie);
        }
    }

    private String getCookieValue(Cookie cookie) {

        StringBuilder builder = new StringBuilder();
        builder.append(cookie.getName()).append(&#39;=&#39;).append(cookie.getValue());
        builder.append(&quot;;Path=&quot;).append(cookie.getPath());
        if (cookie.isHttpOnly()) {
            builder.append(&quot;;HttpOnly&quot;);
        }
        if (cookie.getSecure()) {
            builder.append(&quot;;Secure&quot;);
        }
        // here you can append other attributes like domain / max-age etc.
        builder.append(&quot;;SameSite=None&quot;);
        return builder.toString();
    }
}

答案3

得分: 0

如在此答案中提到:
https://stackoverflow.com/questions/42998367/same-site-flag-for-session-cookie-in-spring-security

@Configuration
public static class WebConfig implements WebMvcConfigurer {
    @Bean
    public TomcatContextCustomizer sameSiteCookiesConfig() {
        return context -> {
            final Rfc6265CookieProcessor cookieProcessor = new Rfc6265CookieProcessor();
            cookieProcessor.setSameSiteCookies(SameSiteCookies.NONE.getValue());
            context.setCookieProcessor(cookieProcessor);
        };
    }
}

但这似乎更简单:

@Configuration
public static class WebConfig implements WebMvcConfigurer {
    @Bean
    public CookieSameSiteSupplier cookieSameSiteSupplier(){
        return CookieSameSiteSupplier.ofNone();
    }
}

或者... 更简单的是,自从Spring Boot 2.6.0以后,可以在application.properties中设置它。

关于SameSite Cookies的Spring文档

server.servlet.session.cookie.same-site = none
英文:

As mentioned in this answer:
https://stackoverflow.com/questions/42998367/same-site-flag-for-session-cookie-in-spring-security

@Configuration
public static class WebConfig implements WebMvcConfigurer {
	@Bean
	public TomcatContextCustomizer sameSiteCookiesConfig() {
		return context -&gt; {
			final Rfc6265CookieProcessor cookieProcessor = new Rfc6265CookieProcessor();
			cookieProcessor.setSameSiteCookies(SameSiteCookies.NONE.getValue());
			context.setCookieProcessor(cookieProcessor);
		};
	}
}

but this seems even simpler

@Configuration
public static class WebConfig implements WebMvcConfigurer {
	@Bean
	public CookieSameSiteSupplier cookieSameSiteSupplier(){
		return CookieSameSiteSupplier.ofNone();
	}
}

Or ... even simpler, spring boot since 2.6.0 supports setting it in application.properties.

Spring documentation about SameSite Cookies

server.servlet.session.cookie.same-site = none

答案4

得分: 0

根据未来的开发人员添加到这个链条中,根据Spring的版本,在代码中修改配置(如其他回答中所示)可能仅会修改嵌入式的Tomcat服务器。如果您的项目部署在现有的Tomcat服务器中,可以通过context.xml为JSessionid添加Samesite属性。然而,有多种设置上下文的方法,请参考此参考链接以确定您的情境。
https://octopus.com/blog/defining-tomcat-context-paths

英文:

Adding to this chain for future devs, depending on the spring version, modifying the configuration via code (as seen in other replies) might only be modifying the embedded tomcat server. If your project is deployed in an existing Tomcat server, adding Samesite to JSessionid would be doable through context.xml. Although, there are several ways to set a context so check this reference to identify your scenario.
https://octopus.com/blog/defining-tomcat-context-paths

huangapple
  • 本文由 发表于 2020年9月17日 21:26:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/63939078.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定