在spring中自动为JSESSIONID cookie添加安全标志



我有一个tomcat应用服务器是在nginx后面。SSL在nginx上终止。部署在tomcat上的Spring web-mvc应用程序应该在JSESSIONID上设置安全标志。如果spring有一些自动检测功能就好了,这样我就不用在开发过程中因为没有SSL而烦恼了。

是否有办法告诉spring自动设置flag ?

我使用JavaConfig来设置应用程序,并使用Maven来创建可部署的war文件。

我已经检查过了,但这看起来有些丑陋和静态:集& # 39;安全# 39;标记JSESSION id cookie

当你使用spring-session时,例如在redis中持久化你的会话,这确实是自动完成的。cookie由org.springframework.session.web.http.CookieHttpSessionStrategy创建,CookieHttpSessionStrategy#createSessionCookie检查请求是否来自HTTPS并相应地设置安全:

sessionCookie.setSecure(request.isSecure());
如果使用spring-session,则可以使用ServletContextInitializer配置安全cookie。使用应用程序属性,根据配置文件将其设置为true/false。
@Bean
public ServletContextInitializer servletContextInitializer(@Value("${secure.cookie}") boolean secure) {
    return new ServletContextInitializer() {
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
            servletContext.getSessionCookieConfig().setSecure(secure);
        }
    };
}

应用程序。属性(当配置文件'prod'不活跃时在dev中使用):

secure.cookie=false

application-prod。属性(仅在配置文件'prod'激活时使用,覆盖application.properties中的值):

secure.cookie=false

在prod服务器上启动应用程序:

--spring.profiles.active=prod

听起来有点费力,如果你到目前为止还没有使用过配置文件,但你很可能需要一个prod环境的配置文件,所以它真的很值得。

如果您正在使用Spring Boot,那么有一个简单的解决方案。只需在application.properties中设置以下属性:

server.servlet.session.cookie.secure=true

来源:Spring docs -附录A.常用应用程序属性

如果你有一些使用HTTPS的环境和一些没有HTTPS的环境,你需要在没有HTTPS的配置文件中将其设置为false。

。Yml只需添加

server:
  session:
    cookie:
      secure: true

在nginx作为ssl终端后,这不是一项简单的任务:安全连接必须由nginx头检测(X-Forwarded-Proto: https,参见使用转发头)
但它很容易解决nginx配置:

if ($scheme = http) {
    return 301 https://$http_host$request_uri;
}
proxy_cookie_path / "/; secure";

我们有一个Spring Boot 2.3应用程序,它在NGINX和Tomcat之间使用HTTPS和HTTP。

即使有这个Spring属性设置:

server:
    servlet:
        session:
            cookie:
                secure: true

…当通过HTTP访问应用程序时,Secure标志是而不是在JSESSIONID cookie上设置。你可以通过在本地运行应用程序并使用HTTP vs HTTP直接访问Tomcat来测试。

我发现添加这个到配置中设置了HTTP和HTTPS的安全标志,这解决了我们使用HTTP将NGINX放在Tomcat前面时的问题:

/**
 * Fix for GCP... since we use HTTP internally in Kubernetes, Spring will not make JSESSIONID Secure, but this will.
 *
 * See https://www.javafixing.com/2021/11/fixed-add-secure-flag-to-jsessionid.html
 *
 * @return
 */
@Bean
public ServletContextInitializer servletContextInitializer() {
    return new ServletContextInitializer() {
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
            servletContext.getSessionCookieConfig().setSecure(true);
        }
    };
}

添加另一个选项

你可以使用ServletContextInitializer来设置安全cookie和http only标志

@Bean
public ServletContextInitializer servletContextInitializer() {
    return new ServletContextInitializer() {
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
            servletContext.setSessionTrackingModes(Collections.singleton(SessionTrackingMode.COOKIE));
            SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig();
            sessionCookieConfig.setHttpOnly(true);
            sessionCookieConfig.setSecure(true);
        }
    };
}

它对我有用

public class WebInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
    AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
    ctx.register(AppConfig.class);
    ctx.setServletContext(servletContext);
    Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
    servlet.addMapping("/");
    servlet.setLoadOnStartup(1);
    servletContext.setSessionTrackingModes(Collections.singleton(SessionTrackingMode.COOKIE));
    SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig();
    sessionCookieConfig.setHttpOnly(true);
    sessionCookieConfig.setSecure(true);
}
}

最新更新