【问题标题】:Add secure flag to JSESSIONID cookie in spring automatically在 spring 中自动将安全标志添加到 JSESSIONID cookie
【发布时间】: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

【问题讨论】:

    标签: java spring spring-mvc cookies nginx


    【解决方案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);
                }
            };
        }
        

        【讨论】:

          猜你喜欢
          • 2019-06-25
          • 1970-01-01
          • 2014-06-11
          • 2017-11-24
          • 1970-01-01
          • 2019-08-29
          • 1970-01-01
          • 2014-02-03
          • 2020-07-06
          相关资源
          最近更新 更多