web-dev-qa-db-ja.com

samesiteでjsessionid cookieを有効にする方法

Wildflyで実行されているWebアプリケーションでSamesiteを有効にするにはどうすればよいですか? standalone.xmlをチェックしましたが、適切なタグが見つかりませんでした

<servlet-container name="default">
    <session-cookie http-only="true" secure="true"/>
    <jsp-config/>
</servlet-container>
7
webyildirim

現時点では、Javaサーブレット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"));
        }
    }
}

2番目のアプローチ(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() {

    }
}

Org.springframework.security.web.authentication.AuthenticationSuccessHandlerまたはjavax.servlet.Filterの構成の詳細については、GitHubの このデモプロジェクト を参照してください。

WebSecurityConfig には、必要なすべての構成が含まれています。

基本的にサーブレットコンテナがセッションとCookieの作成を管理するため、addHeaderの使用は動作が保証されていません。たとえば、アプリケーションサーバーが応答のフラッシュ中にSet-Cookieヘッダーを上書きするため、応答本文でJSONを返す場合、どちらのアプローチも機能しません。ただし、認証が成功した後でユーザーを別のページにリダイレクトする場合、上記のアプローチは機能します。

9
Eugene Maysyuk

回避策の1つは、別の属性(SameSiteなど)を使用してcomment設定をCookieにハッキングすることです。

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

ただし、Undertowはバージョン0またはバージョン1のCookieを使用するときにコメント(およびその他の)値を引用するため、io.undertow.cookie.DEFAULT_ENABLE_RFC6265_COOKIE_VALIDATIONシステムプロパティをtrueに設定してJBoss/WildFlyを実行する必要があります。

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

これにより、望ましい結果が得られます。 cookies

このアプローチは明らかにハックで、Undertow実装の詳細に完全に依存しているため、代わりにWebサーバーまたはロードバランサーレベルで構成することをお勧めします。

5

現在最新リリースのSpring Bootの場合:

最新のspring-boot-starter-Tomcatがない場合は、SameSiteCookies列挙の値UNSETを確認してください。値がない場合は、値SameSite=Noneをスキップするため、新しいリリースが必要です。

@Component
public class SameSiteTomcatCookieProcessorCustomizationBean implements WebServerFactoryCustomizer<TomcatServletWebServerFactory>
{
    @Override
    public void customize(TomcatServletWebServerFactory server) {

        server.getTomcatContextCustomizers().add(new TomcatContextCustomizer()
        {
            @Override
            public void customize(Context context)
            {
                Rfc6265CookieProcessor cookieProcessor = new Rfc6265CookieProcessor();
                cookieProcessor.setSameSiteCookies("None");
                context.setCookieProcessor(cookieProcessor);
            }
        });
    }
}
1
Gábor Ibolya

JBoss EAP 7.2で機能する私の回避策はカスタムハンドラーです。グローバルハンドラーとして使用します。ただし、jboss-web.xmlでも使用できます。 Undertowは同一サイトに対してStrictまたはLaxしか許可しないため、Cookieの実装を試す必要があります( '"UT000162:Same-site attribute 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>
0
Ton Bosma