java - Spring 安全: Set Remember me Service while using AbstractPreAuthenticatedProcessingFilter

标签 java spring spring-mvc authentication spring-security

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

我做了一个没有过滤器的例子,它工作得很好。然后,当我添加过滤器时, Spring 安全性停止使用“记住我”服务。

这是我的 spring 安全配置:

@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;
  }

最佳答案

我通过添加 RememberMeAuthenticationFilter 解决了这个问题,其中我注入(inject)了自定义身份验证管理器和 RememberMe 服务,然后我将 Spring Security 配置为在 AbstractPreAuthenticatedProcessingFilter 之前使用此过滤器

http.addFilter(autoLoginFilter).addFilterBefore(new RememberMeAuthenticationFilter(autoLoginFilter.getAuthenticationManager(), rememberMeServices()),AutoLoginFilter.class)
            .addFilterBefore(new TransactionIdRequestFilter(), AutoLoginFilter.class)
            .exceptionHandling().defaultAuthenticationEntryPointFor(new Http401TimeoutEntryPoint(), matcher)
            .and();

关于java - Spring 安全: Set Remember me Service while using AbstractPreAuthenticatedProcessingFilter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32067830/

相关文章:

java - 如果 JavaFX 发生错误,如何从任何地方调用 setOnCloseRequest 来关闭应用程序?

java - 使 Jtextarea 能够被复制

java - JSON 发布到 Spring Controller

java - 创建EntityManager以及持久化

java - 使用 Spring Security ACL

java编译错误 "could not find or load main class main.java"

SPRING BOOT 使用 Jasig CAS 配置

Spring Boot 使用自动配置创建多个(正常运行的)webmvc 应用程序

javascript - 在非 SPA(单页应用程序)中使用 Require.js 和 Backbone

java - 在 Java 中使用类型化接口(interface)比接收特定类型的方法有什么优势?