gpt4 book ai didi

java - 在 Spring-Boot-Web/Tomcat 中有条件地禁用 JSESSIONID

转载 作者:行者123 更新时间:2023-12-04 17:15:57 25 4
gpt4 key购买 nike

我试图有条件地禁用 JSESSIONID Cookie 的创建。

我只想在请求中存在某个 cookie 时创建此 cookie。

我正在使用 spring-boot-starter-web 2.5.3spring-boot-starter-security

到目前为止我尝试了什么

Spring-Session -> CookieSerializer Bean

我尝试添加 spring-session 并定义自定义 DefaultCookieSerializer-Bean。事实证明,JSESSIONID 实际上不是来自 spring,而是来自底层的 Tomcat。

使用阻止设置 Set-Cookie header 的 javax.servlet.Filter:

package xxxx.configuration;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

@Configuration
public class CookieConsentConfiguration {

private static class CookieConsentFilter implements Filter {

private final ObjectMapper objectMapper;

private CookieConsentFilter(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
final HttpServletRequest req = (HttpServletRequest) request;

if (hasCookieConsent(req)) {
chain.doFilter(request, response);
} else {
chain.doFilter(request, new NoCookiesResponseWrapper((HttpServletResponse) response));
}
}

private boolean hasCookieConsent(HttpServletRequest request) {
try {
final Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("cookie_consent_level")) {
final String value = cookie.getValue();
final JsonNode json = this.objectMapper.readTree(URLDecoder.decode(value, StandardCharsets.US_ASCII));

return json.hasNonNull("strictly-necessary") && json.get("strictly-necessary").booleanValue();
} else if (cookie.getName().equals("cookie_consent_user_accepted")) {
return Boolean.parseBoolean(cookie.getValue());
}
}
}
} catch (Exception e) {
return false;
}

return false;
}
}

private static class NoCookiesResponseWrapper extends HttpServletResponseWrapper {

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

@Override
public void addCookie(Cookie cookie) {
// not allowed
}

@Override
public void setHeader(String name, String value) {
if (!name.equalsIgnoreCase("set-cookie")) {
super.setHeader(name, value);
}
}

@Override
public void addHeader(String name, String value) {
if (!name.equalsIgnoreCase("set-cookie")) {
super.addHeader(name, value);
}
}
}

@Bean
public Filter cookieConsentFilter(ObjectMapper objectMapper) {
return new CookieConsentFilter(objectMapper);
}
}

但这也行不通。 JSESSIONID 仍在创建中。

如果不满足某些条件,是否有任何方法可以禁止创建此(或任何)Cookie?

最佳答案

免责声明:此答案并未直接回答如何停止基于条件创建 JSESSIONID 的问题。出于这个原因,我不会接受这个答案。

GDPR

我发现默认情况下允许严格必要的 cookie,而不需要在向客户端发送 cookie 之前向用户显示 cookie 层。据我了解,您仍然必须在第一页印象时向用户显示 cookie 层。

根据我的理解,这基本上意味着您可以发送 Set-Cookie - 用户第一页加载时绝对必要的 cookie header 。在该页面上,必须显示 cookie 层,但此时可能已经存在绝对必要的 cookie。

有关详细信息,请参阅:https://gdpr.eu/cookies/


技术资料

一般

首先我们要明白在什么情况下会出现一个JSESSIONID已创建。

每当一段代码试图从应用程序服务器获取 session 时,它就会被创建。这意味着,如果我们能够以一种不会尝试从应用程序服务器获取 session 的方式构建我们的代码,则不会 JSESSIONID -Cookie将发送给客户端。

但是也有一些陷阱。对于某些事情, session 是最必要的 cookie:

  • 登录:登录(如网站上的人工用户登录),严格要求 session
  • CSRF-Tokens:服务器需要一些东西来获取这些 token 。这是 session
  • ...更多

Spring-Boot 示例

我正在使用 spring-boot-starter-web在版本 2.5.3 .出于我上面提到的原因之一,我希望仅在真正需要时才创建 session :用户尝试登录或用户访问出于安全原因需要创建 CSRF token 的站点。

第一个相关配置可以在我的WebSecurityConfigurerAdapter中找到:设置 SessionCreationPolicyIF_REQUIRED .

    @Configuration
public static class GlobalWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

@Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/webjars/**", "/css/**", "/js/**");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.and()
.headers()
.frameOptions()
.deny()
.and()
.sessionManagement()// these two lines
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.oauth2Login()
.and()
.logout()
.logoutSuccessUrl("/");
}
}

在我的案例中,第二个相关的事情是只嵌入 CSRF -如果页面确实需要 token 。

我有几个 thymeleaf 模板,我总是使用相同的 <head>部分。在我的每个模板中,我的 <head>部分包括以下几行:

    <meta name="_csrf" th:content="${_csrf.token}"/>
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>

虽然这对于执行 POST 的页面仍然是必需的, PUT , ... - 请求到我的服务器,我的大部分页面都不需要它。

我删除了 CSRF 的使用- 在不需要的每个 thymeleaf 模板中标记。

现在,只有在用户尝试访问包含 JSESSIONID 的页面时,才会从应用程序服务器获取 session (并创建 CSRF) - token

关于java - 在 Spring-Boot-Web/Tomcat 中有条件地禁用 JSESSIONID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68706432/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com