springboot2如何禁用自帶tomcat的session功能
禁用自帶tomcat的session功能
微服務下的各個服務都是無狀態的,所以這個時候tomcat的session管理功能是多餘的,即時不用,也會消耗性能,關閉後tomcat的性能會有提升,但是springboot提供的tomcat沒有配置選項可以直接關閉,研究瞭一下,tomcat默認的session管理器名字叫:StandardManager,查看tomcat加載源碼發現,如果context中沒有Manager的時候,直接new StandardManager(),源碼片段如下:
Manager contextManager = null; Manager manager = getManager(); if (manager == null) { if (log.isDebugEnabled()) { log.debug(sm.getString("standardContext.cluster.noManager", Boolean.valueOf((getCluster() != null)), Boolean.valueOf(distributable))); } if ((getCluster() != null) && distributable) { try { contextManager = getCluster().createManager(getName()); } catch (Exception ex) { log.error(sm.getString("standardContext.cluster.managerError"), ex); ok = false; } } else { contextManager = new StandardManager(); } } // Configure default manager if none was specified if (contextManager != null) { if (log.isDebugEnabled()) { log.debug(sm.getString("standardContext.manager", contextManager.getClass().getName())); } setManager(contextManager); }
為瞭不讓tomcat去new自己的管理器,必須讓第二行的getManager()獲取到對象,所以就可以從這裡入手解決,我的解決辦法如下:自定義一個tomcat工廠,繼承原來的工廠,context中加入自己寫的manager
@Component public class TomcatServletWebServerFactorySelf extends TomcatServletWebServerFactory { protected void postProcessContext(Context context) { context.setManager(new NoSessionManager()); } }
public class NoSessionManager extends ManagerBase implements Lifecycle { @Override protected synchronized void startInternal() throws LifecycleException { super.startInternal(); try { load(); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); t.printStackTrace(); } setState(LifecycleState.STARTING); } @Override protected synchronized void stopInternal() throws LifecycleException { setState(LifecycleState.STOPPING); try { unload(); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); t.printStackTrace(); } super.stopInternal(); } @Override public void load() throws ClassNotFoundException, IOException { log.info("HttpSession 已經關閉,若開啟請配置:seeyon.tomcat.disableSession=false"); } @Override public void unload() throws IOException {} @Override public Session createSession(String sessionId) { return null; } @Override public Session createEmptySession() { return null; } @Override public void add(Session session) {} @Override public Session findSession(String id) throws IOException { return null; } @Override public Session[] findSessions(){ return null; } @Override public void processExpires() {} }
兩個類解決問題,這樣通過request獲取session就是空瞭,tomcat擺脫session這層處理性能有所提升。
禁用內置Tomcat的不安全請求方法
起因:安全組針對接口測試提出的要求,需要關閉不安全的請求方法,例如put、delete等方法,防止服務端資源被惡意篡改。
用過springMvc都知道可以使用@PostMapping、@GetMapping等這種註解限定單個接口方法類型,或者是在@RequestMapping中指定method屬性。這種方式比較麻煩,那麼有沒有比較通用的方法,通過查閱相關資料,答案是肯定的。
tomcat傳統形式通過配置web.xml達到禁止不安全的http方法
<security-constraint> <web-resource-collection> <url-pattern>/*</url-pattern> <http-method>PUT</http-method> <http-method>DELETE</http-method> <http-method>HEAD</http-method> <http-method>OPTIONS</http-method> <http-method>TRACE</http-method> </web-resource-collection> <auth-constraint> </auth-constraint> </security-constraint> <login-config> <auth-method>BASIC</auth-method> </login-config>
Spring boot使用內置tomcat,2.0版本以前使用如下形式
@Bean public EmbeddedServletContainerFactory servletContainer() { TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {// 1 protected void postProcessContext(Context context) { SecurityConstraint securityConstraint = new SecurityConstraint(); securityConstraint.setUserConstraint("CONFIDENTIAL"); SecurityCollection collection = new SecurityCollection(); collection.addPattern("/*"); collection.addMethod("HEAD"); collection.addMethod("PUT"); collection.addMethod("DELETE"); collection.addMethod("OPTIONS"); collection.addMethod("TRACE"); collection.addMethod("COPY"); collection.addMethod("SEARCH"); collection.addMethod("PROPFIND"); securityConstraint.addCollection(collection); context.addConstraint(securityConstraint); } };
2.0版本使用以下形式
@Bean public ConfigurableServletWebServerFactory configurableServletWebServerFactory() { TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); factory.addContextCustomizers(context -> { SecurityConstraint securityConstraint = new SecurityConstraint(); securityConstraint.setUserConstraint("CONFIDENTIAL"); SecurityCollection collection = new SecurityCollection(); collection.addPattern("/*"); collection.addMethod("HEAD"); collection.addMethod("PUT"); collection.addMethod("DELETE"); collection.addMethod("OPTIONS"); collection.addMethod("TRACE"); collection.addMethod("COPY"); collection.addMethod("SEARCH"); collection.addMethod("PROPFIND"); securityConstraint.addCollection(collection); context.addConstraint(securityConstraint); }); return factory; }
關於內嵌tomcat的更多配置,感興趣可以閱讀官方文檔。
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Springboot 使用內置tomcat禁止不安全HTTP的方法
- SpringBoot添加SSL證書的方法
- Javaweb會話跟蹤技術Cookie和Session的具體使用
- 帶你快速上手Servlet
- 關於自定義過濾器獲取不到session問題