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方法

      
         
          /*  
          PUT  
       DELETE  
       HEAD  
       OPTIONS  
       TRACE  
         
         
         
      
      
      BASIC  
    

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的更多配置,感兴趣可以阅读官方文档

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

你可能感兴趣的:(springboot2如何禁用自带tomcat的session功能)