SpringSession的若干问题
在WebSecurity和HttpSecurity中没有配置session的过滤器,为什么每个请求都会被session过滤器过滤,并且还是早于其它过滤器的第一个,因为其它过滤器都可以随意的访问和修改session,并且controller的方法也可以访问?
springsession的应用是通过SessionRepositoryFilter实现的。
经过这一系列的引用和配置操作就保证了在应用启动时,spring的容器里拥有一个包含SessionRepositoryFilter的FilterRegistrationBean。
为什么要这样做呢?是为了编程性的控制tomcat容器启动时加载session过滤器。这又是怎么实现的呢?
接下来通过属性initializers来保存要通过初始化注册到tomcat的过滤器注册器。用属性seen记录已经找到的过滤器,用于判重,防止重复注册。
以上是通过方法addServletContextInitializerBeans()将spring容器中ServletContextInitializer类型的对象加载到tomcat。
接下来是通过方法addAdaptableBeans()将spring容器中Serlet和Filter类型的对象加载到tomcat。
对于SpringSecurity,先通过配置类将WebSecurity构建的过滤器对象注入容器中,然后再通过方法addAdaptableBeans()取出来后构建成RegistrationBean注入到tomcat启动时要用到的initializers集合中。WebSecurity构建的过滤器对象中就包括通过HttpSecurity配置生成的各种业务过滤器,并通过过滤器链串起来。
接下来就是tomcat启动时把这些ServletContextInitializer接口的实现类FilterRegistrationBean启动起来。每个ServletContextInitializer接口的实现类都会被调用方法onStartup()。调用方法onStartup()时会将tomcat容器的上下文对象带过来,然后将一个个过滤器注册到上下文中。
接口ServletContextInitializer提供了方法onStartup()。
抽象类RegistrationBean实现了方法onStartup(),并且定义了抽象方法register()。
抽象类DynamicRegistrationBean实现了方法register(),并且提供会被覆盖的方法addRegistration()和configure()。
抽象类AbstractFilterRegistrationBean提供了最终的方法addRegistration()和configure(),并且了定义需要子类实现的方法getFilter()。
最终的类FilterRegistrationBean提供了接收和返回要注册的Filter的机制。
至于ServletContextInitializer.onStartup()何时被调用及ServletContext.addFilter()是如何被添加到容器上下文的,这就是SpringBoot启动内置tomcat容器的内容了。
至于为什么SessionRepositoryFilter在过滤器中如此靠前,首先是因为它是通过接口ServletContextInitializer的实现类FilterRegistrationBean进行注册的。而ServletContextInitializer类型的注册是早于普通Filter类的。
再者是由于SessionRepositoryFilter的排序基本是最小的。