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

Posted

技术标签:

【中文标题】在 spring 中自动将安全标志添加到 JSESSIONID cookie【英文标题】:Add secure flag to JSESSIONID cookie in spring automatically 【发布时间】:2017-01-08 05:45:20 【问题描述】:

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

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

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

我已经检查过了,但这看起来有点丑陋和静态: set 'secure' flag to JSESSION id cookie

【问题讨论】:

【参考方案1】:

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

sessionCookie.setSecure(request.isSecure());

如果您使用 spring-session,则可以使用 ServletContextInitializer 配置安全 cookie。 使用application property,根据配置文件将其设置为真/假。

@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 环境的配置文件,所以它真的值得。

【讨论】:

CookieHttpSessionStrategy 提到当 HttpServletRequest#isSecure() 返回 true 时会自动添加安全标志。如果 ssl 在 nginx 而不是在 tomcat 上终止,那么该方法如何确定请求确实是通过 https 发送的?或者反过来,我如何告诉 tomcat 请求在某个时候是 ssl 加密的? 一般情况下,您会将 ssl 终结器设置为x-forwarded-proto = https 的请求标头,然后您的 Web 服务器可以使用它来将请求标记为 isSecure。 将secure.cookie 设置为true/false 似乎对我们没有任何帮助。我们在它前面使用了 nginx 和一个 aws 负载均衡器,所以我们需要以某种方式强制它是安全的。有没有办法强制开启? 通常你有自己的开发和生产属性,所以只需在application-prod.property/yaml中设置server.servlet.session.cookie.secure=true【参考方案2】:

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

server.servlet.session.cookie.secure=true

来源:Spring docs - Appendix A. Common application properties

如果您有一些使用 HTTPS 的环境而一些没有使用 HTTPS,则需要在没有 HTTPS 的配置文件中将其设置为 false。否则,安全 cookie 将被忽略。

【讨论】:

【参考方案3】:

在你的 application.yml 中添加

server:
  session:
    cookie:
      secure: true

【讨论】:

改用server: servlet: session: cookie: secure: true server.session.cookie.secure=true in application.properties 对我有用。【参考方案4】:

在 nginx 作为 ssl 终端点之后,这不是一项简单的任务:必须通过 nginx 标头检测安全连接(X-Forwarded-Proto: https,请参阅Using the Forwarded header) 但是通过 nginx config 很容易解决:

if ($scheme = http) 
    return 301 https://$http_host$request_uri;

proxy_cookie_path / "/; secure";

【讨论】:

【参考方案5】:

添加另一个选项

您可以使用 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);
        
    ;

【讨论】:

以上是关于在 spring 中自动将安全标志添加到 JSESSIONID cookie的主要内容,如果未能解决你的问题,请参考以下文章

将维护模式添加到 Spring(安全)应用程序

如何使用命令行将“其他链接器标志”添加到 xcode 项目?

Wordpress 如何向所有 SETCOOKIE() 函数添加 httponly 和安全标志?

为spring webservice添加密码安全性

如何将布局方言添加到spring-boot thymeleaf自动配置文件

Spring 3 将 UserDetails 添加到会话