【发布时间】:2021-08-13 22:56:58
【问题描述】:
我正在尝试有条件地禁用 JSESSIONID Cookie 的创建。
如果请求中存在某个 cookie,我只想创建此 cookie。
我正在使用 spring-boot-starter-web 2.5.3 和 spring-boot-starter-security。
到目前为止我已经尝试过什么
Spring-Session -> CookieSerializer Bean
我尝试添加spring-session 并定义一个自定义DefaultCookieSerializer-Bean。原来JSESSIONID实际上并不是来自spring,而是来自底层的Tomcat。
使用 javax.servlet.Filter 阻止设置 Set-Cookie 标头:
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?
【问题讨论】:
-
如果您出于任何正当理由(例如登录)使用会话,则会话 cookie 是最必要的。
-
我知道,而且我有登录信息。但是 Session-Cookie 是在第一次访问页面时创建的,根本没有尝试登录。此外,我已将 SessionCreationPolicy 设置为 IF_REQUIRED。使用会话的服务器端是否也记住了 CSRF 值?这些可能是创建会话的原因吗?
-
默认使用
LazyCsrfTokenRepository(参见this question),因此除非您使用令牌,否则不会生成会话。您能否提供一个导致问题的页面的最小示例? -
是的,这就是问题所在。我在每个百里香模板中都使用了
csrf标记。这迫使会话被创建 -
@Felix:你能回答你的问题吗?
标签: java spring-boot tomcat