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. Conclusionhtml

   ...
    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>
    java

相關文章
相關標籤/搜索