Как я могу включить тот же сайт для моего веб-приложения, которое работает на wildfly как.
Проверил standalone.xml, но не смог найти подходящий тег в
<servlet-container name = "default">
<session-cookie http-only = "true" secure = "true"/>
<jsp-config/>
</servlet-container>
проверьте тот, который использовал GenericFilterBean / запрос временного перенаправления для решения той же проблемы stackoverflow.com/questions/63939078/…

На данный момент спецификация Java Servlet 4.0 не поддерживает атрибут cookie SameSite. Вы можете увидеть доступные атрибуты, открыв класс Java javax.servlet.http.Cookie.
Однако есть несколько обходных путей. Атрибут Set-Cookie можно переопределить вручную.
Подход №1 (с использованием настраиваемого Spring HttpFirewall и оболочки вокруг запроса):
Вам нужно обернуть запрос и настроить файлы cookie сразу после создания сеанса. Вы можете добиться этого, определив следующие классы:
один bean-компонент (вы можете определить его внутри SecurityConfig, если хотите хранить все в одном месте. Я просто поместил на него аннотацию @Component для краткости)
package hello.approach1;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.web.firewall.FirewalledRequest;
import org.springframework.security.web.firewall.HttpFirewall;
import org.springframework.security.web.firewall.RequestRejectedException;
import org.springframework.stereotype.Component;
@Component
public class CustomHttpFirewall implements HttpFirewall {
@Override
public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
return new RequestWrapper(request);
}
@Override
public HttpServletResponse getFirewalledResponse(HttpServletResponse response) {
return new ResponseWrapper(response);
}
}
первый класс-оболочка
package hello.approach1;
import java.util.Collection;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.http.HttpHeaders;
import org.springframework.security.web.firewall.FirewalledRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* Wrapper around HttpServletRequest that overwrites Set-Cookie response header and adds SameSite=None portion.
*/
public class RequestWrapper extends FirewalledRequest {
/**
* Constructs a request object wrapping the given request.
*
* @param request The request to wrap
* @throws IllegalArgumentException if the request is null
*/
public RequestWrapper(HttpServletRequest request) {
super(request);
}
/**
* Must be empty by default in Spring Boot. See FirewalledRequest.
*/
@Override
public void reset() {
}
@Override
public HttpSession getSession(boolean create) {
HttpSession session = super.getSession(create);
if (create) {
ServletRequestAttributes ra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (ra != null) {
overwriteSetCookie(ra.getResponse());
}
}
return session;
}
@Override
public String changeSessionId() {
String newSessionId = super.changeSessionId();
ServletRequestAttributes ra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (ra != null) {
overwriteSetCookie(ra.getResponse());
}
return newSessionId;
}
private void overwriteSetCookie(HttpServletResponse response) {
if (response != null) {
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=None")); // set
firstHeader = false;
continue;
}
response.addHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=None")); // add
}
}
}
}
второй класс-оболочка
package hello.approach1;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
/**
* Dummy implementation.
* To be aligned with RequestWrapper.
*/
public class ResponseWrapper extends HttpServletResponseWrapper {
/**
* Constructs a response adaptor wrapping the given response.
*
* @param response The response to be wrapped
* @throws IllegalArgumentException if the response is null
*/
public ResponseWrapper(HttpServletResponse response) {
super(response);
}
}
Подход № 2 (с использованием Spring AuthenticationSuccessHandler):
This approach doesn't work for basic authentication. In case basic authentication, response is flushed/committed right after controller returns response object, before SameSiteFilter#addSameSiteCookieAttribute is called.
package hello.approach2;
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"));
}
}
}
Подход № 3 (с использованием javax.servlet.Filter):
This approach doesn't work for basic authentication. In case basic authentication, response is flushed/committed right after controller returns response object, before SameSiteFilter#addSameSiteCookieAttribute is called.
package hello.approach3;
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() {
}
}
Подход №4 (если вы используете Tomcat 9.0.21 / Tomcat 8.5.42 или более поздние версии)
В вашем веб-приложении внутри папки META-INF создайте файл context.xml со следующим содержимым:
Установка для SameSite значения none доступна начиная с Tomcat 9.0.28 / Tomcat 8.5.48)
Подробнее см. этот запрос на перенос.
Демонстрационный проект
Вы можете посмотреть этот демонстрационный проект на GitHub для получения более подробной информации о конфигурации для первых трех подходов.
SecurityConfig содержит всю необходимую конфигурацию.
Using addHeader is not guaranteed to work because basically the Servlet container manages the creation of the Session and Cookie. For example, the second and third approaches won't work in case you return JSON in response body because application server will overwrite Set-Cookie header during flushing of response. However, second and third approaches will work in cases, when you redirect a user to another page after successful authentication.
Pay attention that Postman doesn't render/support SameSite cookie attribute under Cookies section (at least at the time of writing). You can look at Set-Cookie response header or use curl to see if SameSite cookie attribute was added.
После 20 часов отладки я наткнулся на этот ответ. Проблема решена. Большое спасибо, Евгений
@ Венки, я рад, что смог помочь
Как это должно работать, если doFilter запускается до изменения файла cookie? Я пытаюсь это сделать, и мои файлы cookie не изменяются, что бы я ни делал
@Lightheaded, убедитесь, что вы вызываете addSameSiteCookieAttribute () после метода doFilter (). Это гарантирует, что запрос был обработан сервлетом и заголовок «Set-Cookie» уже присутствует в ответе (и готов к перезаписи).
Хорошо, я думаю, моя проблема в другом (например, Tomcat перезаписывает cookie). Спасибо!
@Lightheaded, не могли бы вы описать, как это произошло в вашем случае, когда Tomcat перезаписал заголовок "Set-Cookie", когда у вас будет дополнительная информация о проблеме? Мне может потребоваться обновить сообщение дополнительной информацией. Кстати, у вас есть образец приложения, чтобы я мог воспроизвести проблему, с которой вы столкнулись?
Приложение, с которым я имел дело, было довольно большим и работало со старыми версиями spring (но не с Spring boot), поэтому, к сожалению, у меня нет примеров. В моем случае любые изменения, которые я сделал с файлом cookie программно, не распространялись (т.е. .addHeader() вообще не повлиял). В конце концов, я решил переместить серверную часть в тот же домен и не нашел способа устранить основную причину.
@Lightheaded, не могли бы вы создать образец проекта, который воспроизводит вашу проблему, и загрузить его на github? Я мог бы взглянуть на это и посмотреть, смогу ли я вам помочь.
К сожалению, создание примера проекта для меня - серьезная задача. Я сделаю это, если у меня будет время в ближайшие недели, но, поскольку я все равно решил переписать приложение, это, скорее всего, в данный момент не является разумным вложением времени для меня. Однако я очень ценю ваше предложение о помощи! Спасибо за это!
Вы знаете, почему мои заголовки переменных всегда пусты, даже если я получаю заголовок Set-Cookie в инспекторе?
@WaLinke, могу я взглянуть на ваш код? У вас есть образец кода на GitHub?
Заголовки отправляются первыми в HTTP-запросе, поэтому, если ответ уже был (частично) передан клиенту, это не сработает.
у нас есть только страницы jsp без сервлета, как исправить это в jsp?
@EugeneMaysyuk Я использую первый подход, и, к сожалению, заголовок Set-Cookie еще не отображается в ответе ... Я открыл вопрос, мои классы там, не могли бы вы мне помочь? Тай! stackoverflow.com/questions/67320068/…
@Andre, я ответил на ваш вопрос.
Один из обходных путей - взломать настройку SameSite в cookie с помощью другого атрибута (например, comment):
<servlet-container name = "default">
<jsp-config/>
<session-cookie comment = "; SameSite=None"/>
<websockets/>
</servlet-container>
Но поскольку Undertow цитирует значения комментариев (и других) при использовании файлов cookie версии 0 или 1, JBoss / WildFly должен работать с системным свойством io.undertow.cookie.DEFAULT_ENABLE_RFC6265_COOKIE_VALIDATION, установленным на true:
./bin/standalone.sh -Dio.undertow.cookie.DEFAULT_ENABLE_RFC6265_COOKIE_VALIDATION=true
Это даст вам желаемый результат:

Этот подход, очевидно, является хакерским и полностью зависит от деталей реализации Undertow, поэтому я бы рекомендовал вместо этого настраивать его на уровне веб-сервера или балансировщика нагрузки.
В качестве альтернативы вы можете установить атрибут rfc6265-cookie-validation = true в теге subsystem-> server-> default-server-> http-listener <http-listener name = "default" socket-binding = "http" max-post- size = "10485760000" rfc6265-cookie-validation = "true" redirect-socket = "https" enable-http2 = "true" />
Для 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);
}
});
}
}
Этот ответ мне помог! Мы не используем весеннюю сессию, поэтому другие не применимы.
Мой обходной путь, который работает в JBoss EAP 7.2, - это настраиваемый обработчик. Я использую его как глобальный обработчик. Но вы также можете использовать его в jboss-web.xml. Вам нужно поиграть с реализацией cookie, потому что undertow допускает только Strict или Lax для одного и того же сайта (он выдает '"UT000162: Атрибут Same-site None недопустим. Он должен быть Strict или Lax"', если вы используете cookie.setSameSiteMode ("None" ))
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>
Решение для 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/
У меня возникли проблемы с принятым решением из-за отсутствия заголовка «Set-Cookie» ни для одного из вызовов.
Таким образом, я попробовал другое решение от StackOverflow, конечно, изменив флаги по мере необходимости:
Если вы используете WildFly 19 или новее, рекомендуется определить политику SameSite в файле undertow-handlers.conf. Это довольно гибко, поскольку вы можете определить веб-контекст, в котором будет использоваться политика SameSite, и шаблон регулярного выражения для файлов cookie. Пример:
path(/app2)->samesite-cookie(mode=Lax, cookie-pattern=abc*)
С другой стороны, для приложений Tomcat вы можете добавить файл META-INF / context.xml с атрибутом sameSiteCookies, как в этом примере:
<Context>
<CookieProcessor sameSiteCookies = "strict" />
</Context>
Некоторые ссылки: https://github.com/apache/tomcat/pull/162
Рассматривали ли вы использование Spring Session, поддерживающего cookie на одном сайте с версии 2.1.0.RELEASE? См. github.com/spring-projects/spring-session/blob/2.1.0.RELEASE /…