[英]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.