无法自动从Redis会话中检索securityContext

时间:2019-05-29 08:05:03

标签: spring-boot spring-security spring-session

尝试基于Spring引导构建rest应用程序。 并且我自定义了登录过程,我按照指南手动设置了安全上下文,并且工作正常:

UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(email, password);
Authentication authentication = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetails userDetails = customUserDetailsService.loadUserByUsername(email);
List<String> roles = new ArrayList<String>();
for (GrantedAuthority authority : userDetails.getAuthorities()) {
                roles.add(authority.toString());
            }
// Set security context to session
session.setAttribute("SPRING_SECURITY_CONTEXT",SecurityContextHolder.getContext());

但是当我尝试找回身份验证时,总是会从这些代码中获取 anonymousUser

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();

如果我从会话中手动设置,那没关系,我认为这不是正确的解决方案:

SecurityContext securityContext = (SecurityContext)servletRequest.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
SecurityContextHolder.setContext(securityContext);

我的配置在这里:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig<S extends Session> extends WebSecurityConfigurerAdapter {
    // The max length is 31. The bigger the integer is the longer the time will
    // take.
    // The default value is 10.
    final int ENCODER_STRENTH = 11;

    @Autowired
    @Qualifier("authTokenConfig")
    private AuthTokenConfig authTokenConfig;

    @Autowired
    @Qualifier("customUserDetailsService")
    private UserDetailsService customUserDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // This application is based on RESTful structure, don't need additional CSRF
        // protect.
        http.csrf().disable();
        // The pages does not require login
        http.authorizeRequests().antMatchers("/", "/user/registration", "/login/authenticate", "/login/").permitAll();
        http.apply(authTokenConfig);
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.sessionManagement().sessionFixation().migrateSession();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
        authManagerBuilder.userDetailsService(customUserDetailsService).passwordEncoder(getEncoder());
    }

    @Bean
    public PasswordEncoder getEncoder() {
        return new BCryptPasswordEncoder(ENCODER_STRENTH);
    }

    @Bean
    public UserDetailsService userDetailsService() {
        return super.userDetailsService();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Autowired
    private FindByIndexNameSessionRepository<S> sessionRepository;

    @Bean
    public SpringSessionBackedSessionRegistry<S> sessionRegistry() {
        return new SpringSessionBackedSessionRegistry<>(sessionRepository);
    }

redis配置:

@Configuration
//set the Redis session expiration time
@EnableRedisHttpSession(maxInactiveIntervalInSeconds= 302400)
public class Config {

    @Value("${spring.redis.host}")
    private String redisServer;
    @Value("${spring.redis.port}")
    private int redisPort;
    @Value("${spring.redis.password}")
    private String redisPassword;

    // Create a RedisConnectionFactory that connects Spring Session to the Redis
    // Server.
    @Bean
    @Primary
    public LettuceConnectionFactory redisConnectionFactory() {
        LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder().build();
        RedisStandaloneConfiguration serverConfig = new RedisStandaloneConfiguration(redisServer, redisPort);
        serverConfig.setPassword(redisPassword);
        return new LettuceConnectionFactory(serverConfig, clientConfig);
    }
     @Bean
     public HttpSessionEventPublisher httpSessionEventPublisher() {
             return new HttpSessionEventPublisher();
     }

    // customize Spring Session’s HttpSession integration to use HTTP headers to
    // convey the current session information instead of cookies.
    @Bean
    public HttpSessionIdResolver httpSessionIdResolver() {
        return HeaderHttpSessionIdResolver.xAuthToken(); 
    }

}

初始化器

public class Initializer extends AbstractHttpSessionApplicationInitializer {

}

我已按照Spring Boot指南进行了多次检查,没有任何线索,请帮助我找出可能出问题的地方。谢谢。

1 个答案:

答案 0 :(得分:0)

其原因是缺少以下代码:

http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }