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