spring security session

原文: https://www.baeldung.com/spring-security-session

1. Overview
这里将讲一下 how spring security allows us to control our HTTP sessions
这种控制的范围从session timeout到enabling concurrent session及其它高级security configs.

2. when is the session created?
我们可以精确控制session什么时候被建立,及spring security怎样和它交互:

always - a session will always be created if one doesn't already exist
ifRequired - a session will be created only if required (default)
never - the framework will never create a session ifself but it will use one if it already exists
stateless - no session will be created or used by spring security

<http create-session="ifRequired"> ... </http>
java config
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement()
          .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
}

如果使用stateless, 将会跳过spring security filter chain - 主要session相关部分:
   HttpSessionSecurityContextRepository, SessionManagementFilter, RequestCacheFilter

these more strict control mechanisms have the direct implication(隐含) that COOKIES ARE NOT USED and
so EACH AND EVERY REQUEST NEEDS TO BE RE-AUTHENTICATED.
主要用于REST APIs

3. Under The Hood
执行Authentication process前, spring security将运行一个filter - 它负责在requests之间存储Security Context:  
SecurityCotnextPersistenceFilter.
context将根据一个策略(strategy)进行存储 - HttpSessionSecurityContextRepository(默认) - 这将使用Http Session作为存储
对于stateless, 这个strategy被替换成另一个 - NullSecurityContextRepository.

4. Concurrent Session Control
当一个已经认证过的用户再次试着去authenticate, the application能以几种方式之一处理那个事件。
或者invalidate the active session of user,然后authenticate the user again with a new session,
或者允许两个sessions同时存在

1.允许同时存在的第一步 (web.xml)
<listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

or:

@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
    return new HttpSessionEventPublisher();
}

这确保当session is destroyed, spring security session registry能被通知到

第二步, 为了允许同时存在:
<http ...>
    <session-management>
        <concurrency-control max-sessions="2" />
    </session-management>
</http>

or, via java configuration
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement().maxmumSessions(2);
}

5. Session Timeout
session 超时后,如果用户发送了一个with EXPIRED SESSION ID的请求,这些请求将被redirected到一个URL,
xml配置的URL:
<session-management>
    <concurrency-control expired-url="/sessionExpired.html" .../>
</session-management>

类似,如果session无效(invalid), 重定向的url:
<session-management invalid-session-url="/invalidSession.html">
  ...
</session-management>


相应的java config
http.sessionManagement()
      .expiredUrl("/sessionExpired.html")
      .invalidSessionUrl("/invalidSession.html");

6. Prevent using URL paramenters for Session Tracking
<http> 添加disable-url-rewriting="true" 禁止 url rewrite
web.xml
<session-config>
   <tracking-mode>COOKIE</tracking-mode>
</session-config>

代码方式:
servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));
这选择在哪存放JSESSIONID, in the cookie or in a URL parameter.

7. Session Fixation Proection with Spring Security
会话固定:
防御:spring security在用户登录后,重新生成一个session id

配置当用户再次authenticate,发生什么
<session-management session-fixation-protection="mirgateSession"> ...

java config
http.sessionManagement()
      .sessionFixation().migrateSession()

上面是spring security的默认配置,old session的属性会被复制过来
其它配置:
  none: 原来的session不会invalidated
  newSession: 新建会话,不使用old session里的任何属性

8. Working with the session
session scope的bean定义: 使用@Scope annotation

8.1 Session Scoped Beans
@Component
@Scope("session"
public class Foo { .. }

xml:
<bean id="foo" scope="session"/>

然后,the bean can simply be injected into another bean.
@Autowired
private foo Foo;

And spring will bind the new bean to the lifecycle of the HTTP session

8.2 Injecting the Raw Session into a Controller
the raw HTTP Session can alse be injected directly into a Controller method.
@RequestMapping(...)
public void fooMethod(HttpSession session) {
    session.addAttribute(Constants.FOO, new Foo());
    ...
    Foo foo = (Foo) session.getAttribute(Constants.FOO);
}

8.3 Obtaining the Raw Session
the current HTTP Session can also be obtained programmatically via the RAW Servlet API:
ServletRequestAttributes attr = (ServletRequestAttributes)RequestContextHolder.currentRequestAttributes();
HttpSession session = attr.getRequest().getSession(true); // true = allow create

9. Conclusion

   ...
    OVER

自己加点:(from spring session chapter 5)

1. spring session透明集成HttpSession, 好处:
 .支持集群的sessions.
 .Restful APIs: spring session allows providing session IDs in headers to work with Restful APIs.
2.  和spring security集成
  1. remember me
       ...
  2. spring security concurrent session control
     这个支持集群会话
    要自定义一个Spring security's SessionRegistry接口的实现.
   
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
   @Autowired
   private FindByIndexNameSessionRepository<Session> sessionRepository;

   @Bean
   SpringSessionBackedSessionRegistry sessionRegistry() {
      return new SpringSessionBackedSessionRegistry<>(this.sessionRepository);
   }

   @Override
   protected void configure(HttpSecurity http) throws Exception {
      http
           // other config goes here ...
           .sessionManagement().maximumSessions(2)
           .sessionRegistry(sessionRegistry());
   }

xml:
<security:http>
  <security:session-management>
     <security:concurrency-control max-sessions="2" sesssion-registry-ref="sessionRepostory"/>
  </security:session-management>
</security:http>

<bean id="sessionRegistry" class="org.springframework.session.security.SpringSessionBackedSessionRegistry">
    <constructor-arg ref="sessionRepository"/>
</bean>
   

posted @ 2018-09-09 23:30  北极熊129  阅读(1348)  评论(0编辑  收藏  举报