2017-08-16 89 views
0

我編寫使用Spring Security的應用程序。下面我寫了我的TokenFilter和WebSecurityConfig。 我的問題是SecurityContext包含登錄用戶多長時間? 下一個問題:我的安全配置會話是無狀態的還是沒有? SecurityContext是否替換Session?REST - 創建會話

我的申請是否符合無國籍原則?

public class TokenFilter extends OncePerRequestFilter { 

    @Autowired 
    private UserDetailsService userDetailsService; 

    @Autowired 
    private TokenHelper tokenHelper; 

    private String tokenHeader = "Auth"; 

    @Override 
    protected void doFilterInternal(HttpServletRequest httpServletRequest, 
            HttpServletResponse httpServletResponse, 
            FilterChain filterChain) throws ServletException, IOException { 
     final String authToken = httpServletRequest.getHeader(this.tokenHeader); 

     final String username = tokenHelper.getUsernameFromToken(authToken); 

     if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { 
      final UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); 

      if (tokenHelper.validateToken(authToken, userDetails)) { 
       UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
         userDetails, 
         null, 
         userDetails.getAuthorities() 
       ); 
       authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest)); 
       SecurityContextHolder.getContext().setAuthentication(authentication); 
      } 
     } 

     filterChain.doFilter(httpServletRequest, httpServletResponse); 
    } 
} 

而且安全配置:

@Configuration 
@EnableWebSecurity 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private UnauthorizedHandler unauthorizedHandler; 

    @Autowired 
    private UserDetailsService userDetailsService; 

    @Autowired 
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { 
     authenticationManagerBuilder 
       .userDetailsService(this.userDetailsService) 
       .passwordEncoder(this.passwordEncoder); 
    } 

    @Autowired 
    public BCryptPasswordEncoder passwordEncoder; 

    @Autowired 
    public TokenFilter tokenFilter; 

    @Override 
    protected void configure(HttpSecurity httpSecurity) throws Exception { 
     httpSecurity 
       .csrf().disable() 
       .exceptionHandling().authenticationEntryPoint(unauthorizedHandler) 
       .and() 
       .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
       .and() 
       .authorizeRequests() 
       .antMatchers(HttpMethod.POST, "/login").permitAll() 
       .anyRequest().authenticated(); 

     httpSecurity.addFilterBefore(
       tokenFilter, 
       UsernamePasswordAuthenticationFilter.class 
     ); 

     httpSecurity.headers().cacheControl(); 
    } 
} 

回答

1

SecurityContext僅用於訪問Authentication實例。

SecurityContext可能存儲在您的請求之間。該邏輯(存儲並隨後爲新請求恢復)在SecurityContextPersistenceFilter中執行,該邏輯又將該存儲邏輯委託給SecurityContextRepository

當您使用SessionCreationPolicy.STATELESS,用於NullSecurityContextRepository(它是SecurityContextRepository實現);它實際上並不存儲SecurityContext,它總是「恢復」一個新的(空的)SecurityContext

SessionCreationPolicy.STATELESS也禁止Spring Security在任何形成其機器的bean中創建http會話。

因此,當您使用SessionCreationPolicy.STATELESS時,會話永遠不會創建,並且肯定不會用於存儲SecurityContext。您的每個請求都將有一個全新的安全上下文(其中不包含Authentication),因此您的每個請求都將執行全面的身份驗證。