2017-04-20 101 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来保护,所以我无法解决如何避免重复(并且维护)配置的其余部分。 –