如何为jsessionid cookie启用samesite

时间:2018-04-06 16:40:09

标签: security web cookies wildfly-10

如何为在wildfly上运行的Web应用程序启用samesite。 但是,checked standalone.xml在

中找不到合适的标签
<servlet-container name="default">
    <session-cookie http-only="true" secure="true"/>
    <jsp-config/>
</servlet-container>

7 个答案:

答案 0 :(得分:5)

对于具有当前最新版本的Spring Boot:

如果没有最新的spring-boot-starter-tomcat,请检查SameSiteCookies枚举中的值stdout,如果缺少该值,则需要更新的版本,因为它将跳过值UNSET

SameSite=None

答案 1 :(得分:2)

就目前而言,Java Servlet 4.0规范不支持SameSite cookie属性。您可以通过打开javax.servlet.http.Cookie Java类来查看可用属性。

但是,有两种解决方法。您可以手动覆盖Set-Cookie属性。

第一种方法(使用Spring的AuthenticationSuccessHandler):

import java.io.IOException;
import java.util.Collection;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.HttpHeaders;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
        addSameSiteCookieAttribute(response);    // add SameSite=strict to Set-Cookie attribute
        response.sendRedirect("/hello"); // redirect to hello.html after success auth
    }

    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"));
        }
    }
}

第二种方法(使用javax.servlet.Filter):

import java.io.IOException;
import java.util.Collection;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.HttpHeaders;

public class SameSiteFilter implements javax.servlet.Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        chain.doFilter(request, response);
        addSameSiteCookieAttribute((HttpServletResponse) response); // add SameSite=strict cookie attribute
    }

    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"));
        }
    }

    @Override
    public void destroy() {

    }
}

您可以在GitHub上查看this demo project,以了解有关org.springframework.security.web.authentication.AuthenticationSuccessHandler或javax.servlet.Filter的配置的更多详细信息。

WebSecurityConfig包含所有必需的配置。

  

不能保证使用addHeader,因为基本上   Servlet容器管理会话和Cookie的创建。对于   例如,如果您在中返回JSON,则这两种方法均无效   响应正文,因为应用程序服务器将覆盖Set-Cookie   响应刷新期间的标头。但是,以上方法将   在成功后将用户重定向到另一个页面的情况下可以工作   身份验证。

答案 2 :(得分:2)

一种解决方法是通过使用另一个属性(例如SameSite)将comment设置侵入cookie:

<servlet-container name="default">
    <jsp-config/>
    <session-cookie comment="; SameSite=None"/>
    <websockets/>
</servlet-container>

但是由于Undertow在使用版本0或版本1 cookie时引用了注释(和其他)值,因此JBoss / WildFly需要在io.undertow.cookie.DEFAULT_ENABLE_RFC6265_COOKIE_VALIDATION系统属性设置为true的情况下运行:

 ./bin/standalone.sh -Dio.undertow.cookie.DEFAULT_ENABLE_RFC6265_COOKIE_VALIDATION=true

这将为您提供所需的结果: cookies

这种方法显然是很棘手的,并且完全依赖于Undertow的实现细节,所以我建议改为在Web服务器或负载平衡器级别进行配置。

答案 3 :(得分:2)

我的变通办法是自定义处理程序,它可在JBoss EAP 7.2中使用。我将其用作全局处理程序。但是您也可以在jboss-web.xml中使用它。您需要使用cookie的实现,因为undertow只允许Strict或Lax用于同一站点(它抛出'“ UT000162:同一站点属性None无效。如果您使用cookie.setSameSiteMode(” None“,则它必须为Strict或Lax”' ))

import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.handlers.Cookie;
import java.lang.reflect.Proxy;
import java.util.Map;

public class CookieSameSiteHandler implements HttpHandler
{
   private  HttpHandler next;

   public CookieSameSiteHandler(HttpHandler next){
      this.next = next;
   }

   @Override
   public void handleRequest(final HttpServerExchange exchange)
      throws Exception
   {
      exchange.addResponseCommitListener(serverExchange -> {
         for (Map.Entry<String, Cookie> responcecookie : serverExchange.getResponseCookies().entrySet()){
            serverExchange.getResponseCookies().replace(responcecookie.getKey(), proxyCookie(responcecookie.getValue()));
         }
      });
      next.handleRequest(exchange);
   }

   private Cookie proxyCookie(Cookie cookie)
   {
      return (Cookie)Proxy.newProxyInstance(
         cookie.getClass().getClassLoader(),
         cookie.getClass().getInterfaces(),
         (proxy, method, args) -> {
            if ("isSameSite".equals(method.getName())){
               return true;
            }
            if ("getSameSiteMode".equals(method.getName()) && cookie.getSameSiteMode() == null){
               return "None";
            }
            if ("isSecure".equals(method.getName()) && cookie.getSameSiteMode() == null){
               return true;
            }
            return method.invoke(cookie, args);
         });
   }
}

处理程序配置:

<subsystem xmlns="urn:jboss:domain:undertow:7.0" default-virtual-host="default-host">
    <buffer-cache name="default"/>
    <server name="default-server" default-host="default-host">
        ...
        <host name="default-host" alias="localhost,example.com">
            ...
            <filter-ref name="cookiehandler"/>
            ...
        </host>
    </server>
    ...
    <filters>
        <filter class-name="nl.myownstuff.handler.CookieSameSiteHandler" module="nl.myownstuff.undertow" name="cookiehandler"/>
    </filters>
</subsystem>

答案 4 :(得分:1)

如果您使用 WildFly 19 或更新版本,推荐的方法是在 undertow-handlers.conf 中定义 SameSite 策略。这是非常灵活的,因为您可以定义 Web 上下文,在该上下文下将使用 SameSite 策略和 cookie 的正则表达式模式。 示例:

path(/app2)->samesite-cookie(mode=Lax, cookie-pattern=abc*)

另一方面,对于 Tomcat 应用程序,您可以添加具有 sameSiteCookies 属性的 META-INF/context.xml 文件,如下例所示:

<Context>
   <CookieProcessor sameSiteCookies="strict" />
</Context>

一些参考资料: https://github.com/apache/tomcat/pull/162

How to set SameSite attribute in Web applications

答案 5 :(得分:0)

Wildfly 19.1.0 及更高版本的解决方案:

$ cat src/main/webapp/WEB-INF/undertow-handlers.conf
samesite-cookie(mode=Lax)

资源:https://www.wildfly.org/news/2020/05/04/WildFly-1910-Released/

答案 6 :(得分:0)

由于“Set-Cookie”标头不存在于任何调用中,我在接受的解决方案中遇到了问题。

因此,我尝试了 StackOverflow 的另一种解决方案,当然根据需要更改标志:

Adding flags to existing Jsessionid cookie