Spring Security:使用AbstractPreAuthenticatedProcessingFilter

时间:2015-08-18 08:54:22

标签: java spring spring-mvc authentication spring-security

如何配置spring security以在使用扩展AbstractPreAuthenticatedProcessingFilter和自定义身份验证管理器的customAuthenticationFilter时设置记住我的服务。

我做了一个没有过滤器的例子,它完美无缺。然后,当我使用“记住我的服务”添加过滤器弹簧安全停止时。

这是我的spring security config:

@Configuration
@EnableWebSecurity
public class SecurityContext extends WebSecurityConfigurerAdapter {

  private static final Logger LOGGER = LoggerFactory.getLogger(SecurityContext.class);

  @Autowired
  private CustomUserDetailsService customUserDetailsService;

  @Autowired
  private CCUTokenService ccuTokenService;

  @Autowired
  private PersistanceTokenDaoImpl persistanceTokenDao;

  @Autowired
  private AutoLoginFilter autoLoginFilter;

  /**
   * Spring Security ignores request to static resources such as CSS or JS files. Theses requests
   * will not be intercepted in AutoLoginFilter
   */
  @Override
  public void configure(WebSecurity web) throws Exception {

  // Spring Security ignores request to static resources such as CSS or JS files.
  // theses requests will not be intercepted in AutoLoginFilter
  web.ignoring()
          .antMatchers("/acceptCookies")
          .antMatchers("/assets/**")
          .antMatchers("/v2/api-docs") //swagger-ui
          .antMatchers("/webjars/**")
          .antMatchers("/wro/**")
          .antMatchers("**/frag/**")
          .antMatchers("**/fragment/**")
          .antMatchers("**/script/beginner/**");
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {

    RequestMatcher matcher = new RequestHeaderRequestMatcher("X-Requested-With");

    LOGGER.debug("Creating Security Context ...");

    http.rememberMe().rememberMeServices(rememberMeServices()).key("posc").and();

    http.
    sessionManagement()
    .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().
    csrf().requireCsrfProtectionMatcher(createCSRFMathers()).and();

    //Add autologin filter
    http.addFilter(autoLoginFilter)
            .addFilterBefore(new TransactionIdRequestFilter(), AutoLoginFilter.class)
            .exceptionHandling().defaultAuthenticationEntryPointFor(new Http401TimeoutEntryPoint(), matcher)
            .and();

    //Add form login
    http.formLogin()
            .successHandler(savedRequestAwareAuthenticationSuccessHandler())
            .loginPage("/page/login")
            .loginProcessingUrl("/page/login/authenticate")
            .failureUrl("/page/login?loginError=true")
            .and();

    // Configures the logout function
    http.logout()
            .deleteCookies("JSESSIONID")
            .logoutUrl("/logout")
            .logoutSuccessUrl("/page/login?loginError=false")
            .and();

    // Configures url based authorization
    // Anyone can access the following urls
    http.authorizeRequests()
            .antMatchers("posc://**",
                    "/connectedUser/mobileInfos",
                    "/dashboard/config/**",
                    "/page/checklogintoken/**",
                    "/page/httpError",
                    "/page/login/**",
                    "/page/manifest",
                    "/page/token/**",
                    "/service-scripting/**",
                    "/script/**")
            .permitAll()
            .antMatchers("/**")
            .hasRole("USER");
  }

  private RequestMatcher createCSRFMathers() {

    return new RequestMatcher() {
      private Pattern allowedMethods = Pattern.compile("^GET$");

      private AntPathRequestMatcher[] requestMatchers = {new AntPathRequestMatcher("/script/**"),
              new AntPathRequestMatcher("/page/external/client/**"),
              new AntPathRequestMatcher("/page/token")};

      @Override
      public boolean matches(HttpServletRequest request) {
        if (allowedMethods.matcher(request.getMethod()).matches()) {
          return false;
        }

        for (AntPathRequestMatcher rm : requestMatchers) {
          if (rm.matches(request)) {
            return false;
          }
        }
        return true;
      }
    };
  }

  /**
   * Configures the authentication manager bean which processes authentication requests.
   */
  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
  }

  /**
   * This is used to hash the password of the user.
   */
  @Bean
  public ShaPasswordEncoder passwordEncoder() {
    return new ShaPasswordEncoder(256);
  }

  @Bean   
  public AbstractRememberMeServices rememberMeServices() {

      PersistentTokenBasedRememberMeServices rememberMeServices =
          new PersistentTokenBasedRememberMeServices("posc",customUserDetailsService,persistentTokenRepository());
      rememberMeServices.setAlwaysRemember(true);
      rememberMeServices.setCookieName("remember-me-posc");
      rememberMeServices.setTokenValiditySeconds(1209600);
      return rememberMeServices;
  }

  @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        CassandraTokenRepository db = new CassandraTokenRepository(persistanceTokenDao);
        return db;
    }

    @Bean
    public SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler() {
        SavedRequestAwareAuthenticationSuccessHandler auth = new SavedRequestAwareAuthenticationSuccessHandler();
        auth.setTargetUrlParameter("targetUrl");
        return auth;
    }   
} 

这是我的自定义身份验证管理器:

@Configuration
public class CustomAuthenticationManager implements AuthenticationManager {

  protected static Logger logger = LoggerFactory.getLogger(CustomAuthenticationManager.class);

  @Autowired
  private BaseCoeurService baseCoeurService;

  public CustomAuthenticationManager() {
  }


  public Authentication authenticate(Authentication auth) throws AuthenticationException {
    logger.debug("Performing custom authentication");
    try {
      baseCoeurService.getUserByUsername(auth.getName());
    } catch (ResourceNotFoundException e) {
      throw new BadCredentialsException("User '" + auth.getName() + "' does not exists on BC !");
    } catch(RestException e) {
      throw new BadCredentialsException("Impossible to retrieve User " + auth.getName() + " from BC, cause : " + e.getMessage());
    }
    logger.debug("User details are good and ready to go");
    return new UsernamePasswordAuthenticationToken(auth.getName(), auth.getCredentials(), getAuthorities(1));
  }

  /**
   * Retrieves the correct ROLE type depending on the access level, where access level is an
   * Integer. Basically, this interprets the access value whether it's for a regular user or admin.
   * 
   * @param access an integer value representing the access of the user
   * @return collection of granted authorities
   */
  public Collection<GrantedAuthority> getAuthorities(Integer access) {
    // Create a list of grants for this user
    List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2);

    // All users are granted with ROLE_USER access
    // Therefore this user gets a ROLE_USER by default
    logger.debug("Grant ROLE_USER to this user");
    authList.add(new SimpleGrantedAuthority("ROLE_USER"));

    // Check if this user has admin access
    // We interpret Integer(1) as an admin user
    if (access.compareTo(1) == 0) {
      // User has admin access
      logger.debug("Grant ROLE_ADMIN to this user");
      authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
    }

    // Return list of granted authorities
    return authList;
  }

1 个答案:

答案 0 :(得分:0)

我通过添加一个RememberMeAuthenticationFilter解决了这个问题,我在其中注入了自定义身份验证管理器和rememberMe服务,然后我在SpringPreAuthenticatedProcessingFilter之前配置了spring security以使用此过滤器

.wrapper { border: 1px solid #ccc; width: 200px; height: 200px; }

.title { opacity : 0; transition: opacity .5s ease-in }

.wrapper:hover .title { opacity : 1 }