繁体   English   中英

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

[英]Add secure flag to JSESSIONID cookie in spring automatically

我有一个位于 nginx 后面的 tomcat 应用程序服务器。 SSL 在 nginx 上终止。 部署在 tomcat 上的 Spring web-mvc 应用程序应在 JSESSIONID 上设置安全标志。 如果spring对此有一些自动检测会很酷,这样我就不会在开发过程中受到打扰,因为我没有SSL。

有没有办法告诉spring自动设置标志?

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

我已经检查过了,但这看起来有点丑陋和静态: 将“安全”标志设置为 JSESSION id cookie

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

sessionCookie.setSecure(request.isSecure());

如果使用 spring-session,则可以使用ServletContextInitializer配置安全 cookie。 使用应用程序属性,根据配置文件将其设置为真/假。

@Bean
public ServletContextInitializer servletContextInitializer(@Value("${secure.cookie}") boolean secure) {
    return new ServletContextInitializer() {

        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
            servletContext.getSessionCookieConfig().setSecure(secure);
        }
    };
}

application.properties(在配置文件“prod”未激活时用于开发):

secure.cookie=false

application-prod.properties(仅在配置文件“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。 否则,安全 cookie 将被忽略。

在您的 application.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";

添加另一个选项

您可以使用 ServletContextInitializer 设置安全 cookie 和仅 http 标志

@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);
}
}

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

即使使用此 Spring 属性设置:

server:
    servlet:
        session:
            cookie:
                secure: true

...当通过 HTTP 访问应用程序时,在 JSESSIONID cookie 上设置Secure标志。 您可以通过在本地运行应用程序并使用 HTTP 与 HTTP 直接访问 Tomcat 来测试这一点。

我发现将它添加到配置中会设置 HTTP 和 HTTPS 的 Secure 标志,这解决了使用 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);
        }
    };
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM