Same-Site cookie in Spring Security

2020-03-16 02:48发布

Is it possible to set Same-site Cookie flag in Spring Security?

And if not, is it on a roadmap to add support, please? There is already support in some browsers (i.e. Chrome).

3条回答
小情绪 Triste *
2楼-- · 2020-03-16 03:04

You can always set cookie values by yourself in the Java world if you can get an instance of the HttpServletResponse.

Then you can do:

response.setHeader("Set-Cookie", "key=value; HttpOnly; SameSite=strict")

In spring-security you can easily do this with a filter, here is an example:

public class CustomFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest request,  ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletResponse resp = (HttpServletResponse)response;

        resp.setHeader("Set-Cookie", "locale=de; HttpOnly; SameSite=strict");

        chain.doFilter(request, response);
    }
}

Add this filter to your SecurityConfig like this:

http.addFilterAfter(new CustomFilter(), BasicAuthenticationFilter.class)

Or via XML:

    <http>
        <custom-filter after="BASIC_AUTH_FILTER" ref="myFilter" />
    </http>

<beans:bean id="myFilter" class="org.bla.CustomFilter"/>
查看更多
▲ chillily
3楼-- · 2020-03-16 03:13

Instead of a Filter, In your Authentication Success Handler, you can mention in this way.


    @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                Authentication authentication) throws IOException {
            response.setStatus(HttpServletResponse.SC_OK);
            clearAuthenticationAttributes(request);
            addSameSiteCookieAttribute(response);
            handle(request, response);
        }

        private void addSameSiteCookieAttribute(HttpServletResponse response) {
            Collection<String> headers = response.getHeaders(HttpHeaders.SET_COOKIE);
            boolean firstHeader = true;
            for (String header : headers) { // there can be multiple Set-Cookie attributes
                if (firstHeader) {
                    response.setHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=Strict"));
                    firstHeader = false;
                    continue;
                }
                response.addHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=Strict"));
            }
        }

It was mentioned in one of the answers. Couldn't find the link after I've implemented it.

查看更多
地球回转人心会变
4楼-- · 2020-03-16 03:21

Using the interceptor in SpringBoot.

I'm looking for a resolution for adding SameSite as you, and I only want to add the attribute to the existing "Set-Cookie" instead of creating a new "Set-Cookie". I have tried several ways to meet this requirement, including:
1.adding a custom filter as @unwichtich said,
2.and more I overrode basicAuthenticationFilter. It does add the SameSite attribute. While the timing when Spring will add the "Set-Cookie" is hard to catch. I thought in onAuthenticationSuccess() method, the response must have this header, but it doesn't. I'm not sure whether it's the fault of my custom basicAuthenticationFilter's order.
3.using cookieSerializer, but the spring-session version comes up to a problem. Seems only the latest version support it, but I still can't figure out the version number should be added into the dependency list.
Unfortunately, none of them above can add the samesite well as expected.

Finally, I found the interceptor in spring can help me to make it. It took me a week to get it. Hope this can help you if anyone has the same problem.

@Component
public class CookieServiceInterceptor extends HandlerInterceptorAdapter {

@Override
public boolean preHandle(
   HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

   return true;
}

@Override
public void postHandle(
   HttpServletRequest request, HttpServletResponse response, Object handler, 
   ModelAndView modelAndView) throws Exception {
    //check whether it has "set-cookie" in the response, if it has, then add "SameSite" attribute
    //it should be found in the response of the first successful login
    Collection<String> headers = response.getHeaders(HttpHeaders.SET_COOKIE);
    boolean firstHeader = true;
    for (String header : headers) { // there can be multiple Set-Cookie attributes
        if (firstHeader) {
            response.setHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s",  header, "SameSite=strict"));
            firstHeader = false;
            continue;
        }
        response.addHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s",  header, "SameSite=strict"));
    }
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
   Object handler, Exception exception) throws Exception {}
}

and you also need to make this interceptor work in your application, which means you should add a bean as below:

   @Autowired
   CookieServiceInterceptor cookieServiceInterceptor;

   @Bean
  public MappedInterceptor myInterceptor()
  {
     return new MappedInterceptor(null, cookieServiceInterceptor);
  }
查看更多
登录 后发表回答