2015-04-10 5 views
7

sto incontrando un problema con il mio ricordo mi configurazione:Problema con Primavera di sicurezza, ricordati di me non Token essere impostato su SecurityContextHolder

[nio-8080-exec-8] s.s.w.a.r.RememberMeAuthenticationFilter : SecurityContextHolder not populated with remember-me token, as it already contained: 'org.springframew[email protected]73939efa: Principal: Member ... 

Qui è la mia configurazione di sicurezza Primavera:

@Configuration 
@EnableWebSecurity 
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private MemberUserDetailsService memberUserDetailsService; 

    @Autowired 
    private BCryptPasswordEncoder passwordEncoder; 

    @Autowired 
    private AccessDecisionManager accessDecisionManager; 

    @Autowired 
    private ApplicationEventPublisher eventPublisher; 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     //@formatter:off 
     http 
     .headers() 
     .cacheControl() 
      .and() 
     .and() 
     .csrf() 
     .csrfTokenRepository(csrfTokenRepository()) 
     .and() 
     .rememberMe() 
     .tokenValiditySeconds(60*60*24*7) 
     .and() 
      .exceptionHandling() 
      .accessDeniedHandler(accessDeniedHandler()) 
     .and() 
      .formLogin() 
      .loginProcessingUrl("/api/signin") 
      .failureHandler(authenticationFailureHandler()) 
      .successHandler(authenticationSuccessHandler()) 
     .and() 
      .logout() 
      .logoutRequestMatcher(new AntPathRequestMatcher("/api/signout")) 
      .logoutSuccessHandler(logoutSuccessHandler()) 
     .and() 
      .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class) 
      .authorizeRequests() 
       .accessDecisionManager(accessDecisionManager) 
       .antMatchers("/resources/**", "/**").permitAll() 
       .anyRequest().authenticated(); 
     //@formatter:on 
    } 

    private LogoutSuccessHandler logoutSuccessHandler() { 
     return new LogoutSuccessHandler() { 
      @Override 
      public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { 
       response.setStatus(HttpStatus.OK.value()); 
      } 
     }; 
    } 

    private AccessDeniedHandler accessDeniedHandler() { 
     return new AccessDeniedHandler() { 
      @Override 
      public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { 
       // TODO: deal with InvalidCsrfTokenException 
       response.setStatus(HttpStatus.FORBIDDEN.value()); 
      } 
     }; 
    } 

    private AuthenticationFailureHandler authenticationFailureHandler() { 
     return new AuthenticationFailureHandler() { 
      @Override 
      public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { 
       response.setStatus(HttpStatus.UNAUTHORIZED.value()); 
      } 
     }; 
    } 

    private AuthenticationSuccessHandler authenticationSuccessHandler() { 
     return new AuthenticationSuccessHandler() { 
      @Override 
      public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { 
       Member member = (Member) authentication.getPrincipal(); 
       eventPublisher.publishEvent(new SigninApplicationEvent(member)); 
       // TODO: overhaul below 
       response.addHeader("MEMBER_ROLE", member.getRole().name()); 
       response.setStatus(HttpStatus.OK.value()); 
      } 
     }; 
    } 

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

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.userDetailsService(memberUserDetailsService).passwordEncoder(passwordEncoder); 
    } 

    private CsrfTokenRepository csrfTokenRepository() { 
     HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); 
     repository.setHeaderName("X-XSRF-TOKEN"); 
     return repository; 
    } 
} 

e anche:

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
public class CoreSecurityConfiguration { 

    @Bean 
    public MemberUserDetailsService memberUserDetailsService() { 
     return new MemberUserDetailsService(); 
    } 

    @Bean 
    public BCryptPasswordEncoder passwordEncoder() { 
     BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); 
     return passwordEncoder; 
    } 

    @Bean 
    public SessionRegistryImpl sessionRegistry() { 
     SessionRegistryImpl sessionRegistry = new SessionRegistryImpl(); 
     return sessionRegistry; 
    } 

    @Bean 
    public AffirmativeBased accessDecisionManager() { 
     AffirmativeBased accessDecisionManager = new AffirmativeBased(accessDecisionVoters()); 
     return accessDecisionManager; 
    } 

    private List<AccessDecisionVoter<? extends Object>> accessDecisionVoters() { 
     List<AccessDecisionVoter<? extends Object>> accessDecisionVoters = new ArrayList<>(); 
     accessDecisionVoters.add(roleHierarchyVoter()); 
     accessDecisionVoters.add(webExpressionVoter()); 
     return accessDecisionVoters; 
    } 

    @Bean 
    public WebExpressionVoter webExpressionVoter() { 
     WebExpressionVoter webExpressionVoter = new WebExpressionVoter(); 
     webExpressionVoter.setExpressionHandler(defaultWebSecurityExpressionHandler()); 
     return webExpressionVoter; 
    } 

    @Bean 
    public DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler() { 
     DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); 
     defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy()); 
     return defaultWebSecurityExpressionHandler; 
    } 

    @Bean 
    public RoleHierarchyVoter roleHierarchyVoter() { 
     RoleHierarchyVoter roleHierarchyVoter = new RoleHierarchyVoter(roleHierarchy()); 
     return roleHierarchyVoter; 
    } 

    @Bean 
    public RoleHierarchyImpl roleHierarchy() { 
     RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); 
     //@formatter:off 
     roleHierarchy.setHierarchy(
       "ROLE_ADMINISTRATOR > ROLE_MODERATOR\n" + 
       "ROLE_MODERATOR > ROLE_SUBSCRIBED_PARENTS\n" + 
       "ROLE_MODERATOR > ROLE_SUBSCRIBED_CHILDCARE_WORKER\n" + 
       "ROLE_SUBSCRIBED_PARENTS > ROLE_BASIC_PARENTS\n" + 
       "ROLE_SUBSCRIBED_CHILDCARE_WORKER > ROLE_BASIC_CHILDCARE_WORKER"); 
     //@formatter:on 
     return roleHierarchy; 
    } 

} 

Qualcuno può aiutarmi?

modificare 1:

MemberUserDetailsService:

@Component 
public class MemberUserDetailsService implements UserDetailsService { 

    @Autowired 
    private MemberRepository memberRepository; 

    @Override 
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { 
     Member member = memberRepository.findByEmail(email); 
     if (member == null) { 
      throw new UsernameNotFoundException("Username: " + email + " not found!"); 
     } 
     return member; 
    } 

} 

Edit 2: Ecco la nuova configurazione:

@Configuration 
@EnableWebSecurity 
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private MemberUserDetailsService memberUserDetailsService; 

    @Autowired 
    private BCryptPasswordEncoder passwordEncoder; 

    @Autowired 
    private AccessDecisionManager accessDecisionManager; 

    @Autowired 
    private ApplicationEventPublisher eventPublisher; 

    @Autowired 
    private CsrfTokenRepository csrfTokenRepository; 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     //@formatter:off 
     http 
     .headers() 
     .cacheControl() 
      .and() 
     .and() 
     .csrf() 
     .csrfTokenRepository(csrfTokenRepository()) 
     .and() 
     .rememberMe() 
     .key("myKey") 
     .tokenValiditySeconds(60*60*24*7) 
     .userDetailsService(memberUserDetailsService) 
     .and() 
      .exceptionHandling() 
      .accessDeniedHandler(accessDeniedHandler()) 
     .and() 
      .formLogin() 
      .loginProcessingUrl("/api/signin") 
      .failureHandler(authenticationFailureHandler()) 
      .successHandler(authenticationSuccessHandler()) 
     .and() 
      .logout() 
      .logoutRequestMatcher(new AntPathRequestMatcher("/api/signout")) 
      .logoutSuccessHandler(logoutSuccessHandler()) 
     .and() 
      .addFilter(usernamePasswordAuthenticationFilter()) 
      .addFilter(rememberMeAuthenticationFilter()) 
      .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class) 
      .authorizeRequests() 
       .accessDecisionManager(accessDecisionManager) 
       .antMatchers("/resources/**", "/**").permitAll() 
       .anyRequest().authenticated(); 
     //@formatter:on 
    } 

    private LogoutSuccessHandler logoutSuccessHandler() { 
     return new LogoutSuccessHandler() { 
      @Override 
      public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { 
       response.setStatus(HttpStatus.OK.value()); 
      } 
     }; 
    } 

    private AccessDeniedHandler accessDeniedHandler() { 
     return new AccessDeniedHandler() { 
      @Override 
      public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { 
       // TODO: deal with InvalidCsrfTokenException & MissingCsrfTokenException 
       response.setStatus(HttpStatus.FORBIDDEN.value()); 
      } 
     }; 
    } 

    private AuthenticationFailureHandler authenticationFailureHandler() { 
     return new AuthenticationFailureHandler() { 
      @Override 
      public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { 
       response.setStatus(HttpStatus.UNAUTHORIZED.value()); 
      } 
     }; 
    } 

    private AuthenticationSuccessHandler authenticationSuccessHandler() { 
     return new AuthenticationSuccessHandler() { 
      @Override 
      public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { 
       response.setStatus(HttpStatus.OK.value()); 
       Member member = (Member) authentication.getPrincipal(); 
       eventPublisher.publishEvent(new SigninApplicationEvent(member)); 
       response.setStatus(HttpStatus.OK.value()); 
       // TODO: overhaul below 
       response.addHeader("MEMBER_ROLE", member.getRole().name()); 
      } 
     }; 
    } 

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

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.authenticationProvider(rememberMeAuthenticationProvider()).userDetailsService(memberUserDetailsService).passwordEncoder(passwordEncoder); 
    } 

    @Bean 
    protected CsrfTokenRepository csrfTokenRepository() { 
     HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); 
     repository.setHeaderName("X-XSRF-TOKEN"); 
     return repository; 
    } 

    @Bean 
    public RememberMeAuthenticationProvider rememberMeAuthenticationProvider() { 
     return new RememberMeAuthenticationProvider("myKey"); 
    } 

    @Bean 
    public RememberMeServices rememberMeServices() { 
     return new TokenBasedRememberMeServices("myKey", memberUserDetailsService); 
    } 

    @Bean 
    public RememberMeAuthenticationFilter rememberMeAuthenticationFilter() throws Exception { 
     return new RememberMeAuthenticationFilter(authenticationManager(), rememberMeServices()); 
    } 

    @Bean 
    public UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter() throws Exception { 
     UsernamePasswordAuthenticationFilter filter = new UsernamePasswordAuthenticationFilter(); 
     filter.setRememberMeServices(rememberMeServices()); 
     filter.setAuthenticationManager(authenticationManager()); 
     return filter; 
    } 

} 
+0

Descrivi i passaggi che hanno portato a questo problema. – Mithun

+0

I passaggi che portano al problema sono solo un accesso di sicurezza di primavera. – balteo

+0

Si prega di condividere il codice per 'MemberUserDetailsService' pure. – Mithun

risposta

3

Dal momento che non è stato specificato il servizio di ricordare-me tipo di implementazione, TokenBasedRememberMeServices viene utilizzato per impostazione predefinita.

quando si utilizza TokenBasedRememberMeServices Si prega di trovare la nota di seguito dalla documentazione:

Non dimenticate di aggiungere il RememberMeServices implementazione per la vostra proprietà UsernamePasswordAuthenticationFilter.setRememberMeServices(), includono il RememberMeAuthenticationProvider nella vostra AuthenticationManager.setProviders() lista, e aggiungere RememberMeAuthenticationFilter nel tuo FilterChainProxy (tipicamente subito dopo il tuo UsernamePasswordAuthenticationFilter)

è necessario effettuare le seguenti modifiche:

  1. In configure() metodo è necessario aggiungere una chiave e filtri

    http.rememberMe().key("yourKey")

    .addFilter(usernamePasswordAuthenticationFilter()) .addFilter(rememberMeAuthenticationFilter())

  2. Creare UsernamePasswordAuthenticationFilter e RememberMeAuthenticationFilter

    @Bean 
    public UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter() 
           throws Exception { 
        UsernamePasswordAuthenticationFilter filter = 
           new UsernamePasswordAuthenticationFilter(); 
        filter.setRememberMeServices(memberUserDetailsService);  
        filter.setAuthenticationManager(authenticationManager()); 
        return filter; 
    } 
    
    @Bean 
    public RememberMeAuthenticationFilter rememberMeAuthenticationFilter() 
            throws Exception { 
        RememberMeAuthenticationFilter filter = 
          new RememberMeAuthenticationFilter(authenticationManager(), memberUserDetailsService); 
        return filter; 
    } 
    
  3. Aggiungere RememberMeAuthenticationProvider alla lista dei fornitori:

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) 
        throws Exception {    
        auth.userDetailsService(memberUserDetailsService) 
         .passwordEncoder(passwordEncoder) 
         .and() 
         .authenticationProvider(new RememberMeAuthenticationProvider("yourKey")); 
    } 
    
+0

Grazie per il tuo contributo. Ho provato il codice fornito. Ha due errori però: nel 'filtro.setRememberMeServices (memberUserDetailsService); '&' new RememberMeAuthenticationFilter (authenticationManager(), memberUserDetailsService); '** memberUserDetailsService ** dovrebbe essere ** rememberMeServices **? – balteo

+0

Purtroppo non sembra funzionare. Sto modificando il mio post per riflettere i cambiamenti esatti. E l'ordine dei filtri? Importa? – balteo

+0

Grazie per le misure. Per quanto riguarda l'ordinamento dei filtri, 'UsernamePasswordAuthenticationFilter' dovrebbe venire prima di' RememberMeAuthenticationFilter' nella catena di filtri, che è già stata presa in considerazione nella configurazione. Solo un altro cambiamento, non so se funzionerà, potresti rimuovere 'CsrfHeaderFilter' e provare. – Mithun

Problemi correlati