2017-04-20 97 views
4

TL; DR春季會話創建策略每個請求?

是否有可能在每個請求的基礎上控制在春季(安全)會議創建策略?

長版...

我一直使用正常的登錄表單的用戶認證爲我們的應用程序。 一些控制器是@RestControllers,到目前爲止,cookie跟蹤的默認用戶會話允許它正常工作。

我現在想允許一些@RestController端的(即當一個XHR請求來自一個頁面,瀏覽器發送的cookie JSESSIONID照常請求進行認證以在用戶的​​先前記錄)指向從其餘客戶端而不是瀏覽器調用,所以我創建了一個API令牌認證方案 - 這工作正常。

一個清理的最後一位的是,REST調用生成會話,我想盡可能避免它。

我不能設置會話策略,以NEVER(因爲我仍然依靠會話我的網絡用戶)。

我試圖IF_REQUIRED無濟於事。

我已經看了看HttpSessionSecurityContextRepository但它包裝的要求,並且每當響應刷新創建一個會話。

(請參見下面的堆棧跟蹤)

是否有可能在別處掛接到會話管理上的每個請求的基礎?

我可以區分的請求容易地夠基於所述類型的Authentication對象的類型。

at myapp.cfg.WebConfig$1.sessionCreated(WebConfig.java:74) 
at io.undertow.servlet.core.ApplicationListeners.sessionCreated(ApplicationListeners.java:300) 
at io.undertow.servlet.core.SessionListenerBridge.sessionCreated(SessionListenerBridge.java:56) 
at io.undertow.server.session.SessionListeners.sessionCreated(SessionListeners.java:52) 
at io.undertow.server.session.InMemorySessionManager.createSession(InMemorySessionManager.java:187) 
at io.undertow.servlet.spec.ServletContextImpl.getSession(ServletContextImpl.java:741) 
at io.undertow.servlet.spec.HttpServletRequestImpl.getSession(HttpServletRequestImpl.java:370) 
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:270) 
at org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper.createNewSessionIfAllowed(HttpSessionSecurityContextRepository.java:427) 
at org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper.saveContext(HttpSessionSecurityContextRepository.java:364) 
at org.springframework.security.web.context.SaveContextOnUpdateOrErrorResponseWrapper.onResponseCommitted(SaveContextOnUpdateOrErrorResponseWrapper.java:85) 
at org.springframework.security.web.util.OnCommittedResponseWrapper.doOnResponseCommitted(OnCommittedResponseWrapper.java:245) 
at org.springframework.security.web.util.OnCommittedResponseWrapper.access$000(OnCommittedResponseWrapper.java:33) 
at org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.flush(OnCommittedResponseWrapper.java:512) 
at org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.flush(OnCommittedResponseWrapper.java:513) 
at com.fasterxml.jackson.core.json.UTF8JsonGenerator.flush(UTF8JsonGenerator.java:1050) 
at com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:953) 

回答

2

拆分您的安全配置成表單登錄(基於會話的API訪問)和無狀態的API令牌認證計劃獨立的部分。

例子:

@Configuration 
@EnableWebSecurity 
public class SecurityConfiguration { 

    @Order(1) 
    @Configuration 
    class ApiSecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .antMatcher("/api/**") 
      .authorizeRequests().anyRequest().authenticated() 
      .and() 
      .httpBasic().realmName("API") // your API token authentication scheme 
      .and() 
      .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER) 
      .and() 
      .exceptionHandling().authenticationEntryPoint(new Http401AuthenticationEntryPoint("Form realm=\"API\"")); // prevent basic authentication popup in browser 
    } 
    } 

    @Order(2) 
    @Configuration 
    class DefaultSecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .formLogin().loginPage("/login").permitAll() 
      .and() 
      .logout().logoutSuccessUrl("/login").permitAll(); 
    } 
    } 
} 

替換.httpBasic().realmName("API")與你自己的身份驗證方案。

致電聯絡,例如您的API curl -v ...並確認響應中沒有Set-Cookie標頭。否則你的代碼會自行創建一個http會話。

+0

感謝卡米爾。這看起來像一個非常好的方法。我會盡快試用並報告。 –

+0

祝你好運!讓我知道它是否適合你。 –

+0

我已經給了這個去,但似乎無法找到正確的配置。經過實驗,似乎每個請求只使用一個HttpSecurity鏈。特定的http.antMatcher(...)在這裏促進了APISecurityConfiguration的使用。但是(幾乎)整個後端可以通過session-auth或session-less api key來保護,所以我無法解決如何避免重複(並且維護)配置的其餘部分。 –