java - 扩展 SimpleUrlAuthenticationFailureHandler 会产生 404 和 No mapping found 警告

标签 java spring spring-mvc spring-security

我正在尝试扩展 SimpleUrlAuthenticationFailureHandler 以在 spring security 中的身份验证失败时实现一些自定义功能。我所有的配置都是在 java 代码中,所以没有安全 xml 文件等。CustomAuthenticationFailureHandler 的代码如下;

public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler{

    public CustomAuthenticationFailureHandler(String defaultFailureUrl) {
        super(defaultFailureUrl);
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        String userName = request.getParameter("username");
        System.out.println("Invalid login attempt by user " + userName);
        // This performs custom auditing upon each login failure
        userLogRepository.logUserActivity(userName, -1, request.getRemoteHost(), exception);
        super.onAuthenticationFailure(request, response, exception);
    }
}

并且此处理程序如下应用于 spring 安全性;

public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
@Qualifier("userDetailsService")
UserDetailsService userDetailsService;

@Autowired
@Qualifier("userLogRepository")
UserLogRepository userLogRepository;

@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {

    auth.userDetailsService(userDetailsService);
}

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

     CsrfTokenResponseHeaderBindingFilter csrfTokenFilter = new CsrfTokenResponseHeaderBindingFilter();
     http.addFilterAfter(csrfTokenFilter, CsrfFilter.class);


     http.authorizeRequests().antMatchers("/rest/**").access("hasRole('ROLE_REST_USER')")
        .and().formLogin().successHandler(new CustomLoginSuccessHandler(new AjaxAuthenticationSuccessHandler(new SavedRequestAwareAuthenticationSuccessHandler())))
        // If I use the following failureUrl method it all seems to work correctly but then I don't have the custom implementaiton. 
        //.failureUrl("/login?error=1").permitAll()
        .failureHandler(new CustomAuthenticationFailureHandler("/login?error=1"))
        .and().logout().invalidateHttpSession(true).addLogoutHandler(new CustomLogoutSuccessHandler()).permitAll()
        .and().exceptionHandling().accessDeniedPage("/403")
        .and().csrf();

}

我已将 org.springframework.security 包置于 Debug模式日志记录中,这两个配置 1) 使用 failureUrl 和 2) 使用自定义故障处理程序。在下面的日志片段中,如果使用 failureUrl 配置,DefaultLoginPageGeneratingFilter 似乎正确重定向到“/login?error=1”。

使用 failureUrl 方法(有效)

2016-10-06 15:43:24,839 [http-bio-8080-exec-5 : DEBUG] SimpleUrlAuthenticationFailureHandler : Redirecting to /login?error=1
2016-10-06 15:43:24,839 [http-bio-8080-exec-5 : DEBUG] DefaultRedirectStrategy : Redirecting to '/web-console/login?error=1'
2016-10-06 15:43:24,840 [http-bio-8080-exec-5 : DEBUG] HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@798d735c
2016-10-06 15:43:24,840 [http-bio-8080-exec-5 : DEBUG] HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2016-10-06 15:43:24,840 [http-bio-8080-exec-5 : DEBUG] SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2016-10-06 15:43:24,843 [http-bio-8080-exec-6 : DEBUG] FilterChainProxy : /login?error=1 at position 1 of 14 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-10-06 15:43:24,843 [http-bio-8080-exec-6 : DEBUG] FilterChainProxy : /login?error=1 at position 2 of 14 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-10-06 15:43:24,844 [http-bio-8080-exec-6 : DEBUG] HttpSessionSecurityContextRepository : HttpSession returned null object for SPRING_SECURITY_CONTEXT
2016-10-06 15:43:24,844 [http-bio-8080-exec-6 : DEBUG] HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@4ef1ae10. A new one will be created.
2016-10-06 15:43:24,844 [http-bio-8080-exec-6 : DEBUG] FilterChainProxy : /login?error=1 at position 3 of 14 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2016-10-06 15:43:24,844 [http-bio-8080-exec-6 : DEBUG] FilterChainProxy : /login?error=1 at position 4 of 14 in additional filter chain; firing Filter: 'CsrfFilter'
2016-10-06 15:43:24,844 [http-bio-8080-exec-6 : DEBUG] FilterChainProxy : /login?error=1 at position 5 of 14 in additional filter chain; firing Filter: 'CsrfTokenResponseHeaderBindingFilter'
2016-10-06 15:43:24,844 [http-bio-8080-exec-6 : DEBUG] FilterChainProxy : /login?error=1 at position 6 of 14 in additional filter chain; firing Filter: 'LogoutFilter'
2016-10-06 15:43:24,844 [http-bio-8080-exec-6 : DEBUG] AntPathRequestMatcher : Request 'GET /login' doesn't match 'POST /logout
2016-10-06 15:43:24,844 [http-bio-8080-exec-6 : DEBUG] FilterChainProxy : /login?error=1 at position 7 of 14 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2016-10-06 15:43:24,844 [http-bio-8080-exec-6 : DEBUG] AntPathRequestMatcher : Request 'GET /login' doesn't match 'POST /login
2016-10-06 15:43:24,844 [http-bio-8080-exec-6 : DEBUG] FilterChainProxy : /login?error=1 at position 8 of 14 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
2016-10-06 15:43:24,844 [http-bio-8080-exec-6 : DEBUG] HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@798d735c
2016-10-06 15:43:24,844 [http-bio-8080-exec-6 : DEBUG] HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2016-10-06 15:43:24,845 [http-bio-8080-exec-6 : DEBUG] SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed

使用自定义故障处理程序(这不起作用)

2016-10-06 15:37:20,413 [http-bio-8080-exec-6 : DEBUG] DefaultRedirectStrategy : Redirecting to '/web-console/login?error=1'
2016-10-06 15:37:20,413 [http-bio-8080-exec-6 : DEBUG] HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@26019c88
2016-10-06 15:37:20,414 [http-bio-8080-exec-6 : DEBUG] HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2016-10-06 15:37:20,414 [http-bio-8080-exec-6 : DEBUG] SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2016-10-06 15:37:20,417 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 1 of 14 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2016-10-06 15:37:20,417 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 2 of 14 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2016-10-06 15:37:20,417 [http-bio-8080-exec-7 : DEBUG] HttpSessionSecurityContextRepository : HttpSession returned null object for SPRING_SECURITY_CONTEXT
2016-10-06 15:37:20,417 [http-bio-8080-exec-7 : DEBUG] HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@58e4d010. A new one will be created.
2016-10-06 15:37:20,418 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 3 of 14 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2016-10-06 15:37:20,418 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 4 of 14 in additional filter chain; firing Filter: 'CsrfFilter'
2016-10-06 15:37:20,418 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 5 of 14 in additional filter chain; firing Filter: 'CsrfTokenResponseHeaderBindingFilter'
2016-10-06 15:37:20,418 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 6 of 14 in additional filter chain; firing Filter: 'LogoutFilter'
2016-10-06 15:37:20,418 [http-bio-8080-exec-7 : DEBUG] AntPathRequestMatcher : Request 'GET /login' doesn't match 'POST /logout
2016-10-06 15:37:20,418 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 7 of 14 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2016-10-06 15:37:20,418 [http-bio-8080-exec-7 : DEBUG] AntPathRequestMatcher : Request 'GET /login' doesn't match 'POST /login
2016-10-06 15:37:20,418 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 8 of 14 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
2016-10-06 15:37:20,418 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 9 of 14 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2016-10-06 15:37:20,418 [http-bio-8080-exec-7 : DEBUG] DefaultSavedRequest : pathInfo: both null (property equals)
2016-10-06 15:37:20,418 [http-bio-8080-exec-7 : DEBUG] DefaultSavedRequest : queryString: arg1=null; arg2=error=1 (property not equals)
2016-10-06 15:37:20,418 [http-bio-8080-exec-7 : DEBUG] HttpSessionRequestCache : saved request doesn't match
2016-10-06 15:37:20,419 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 10 of 14 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2016-10-06 15:37:20,419 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 11 of 14 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2016-10-06 15:37:20,419 [http-bio-8080-exec-7 : DEBUG] AnonymousAuthenticationFilter : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 99432565D3173E5497B49BC0DF428692; Granted Authorities: ROLE_ANONYMOUS'
2016-10-06 15:37:20,419 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 12 of 14 in additional filter chain; firing Filter: 'SessionManagementFilter'
2016-10-06 15:37:20,419 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 13 of 14 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2016-10-06 15:37:20,419 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 at position 14 of 14 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2016-10-06 15:37:20,419 [http-bio-8080-exec-7 : DEBUG] AntPathRequestMatcher : Request 'GET /login' doesn't match 'POST /logout
2016-10-06 15:37:20,419 [http-bio-8080-exec-7 : DEBUG] AntPathRequestMatcher : Checking match of request : '/login'; against '/rest/**'
2016-10-06 15:37:20,419 [http-bio-8080-exec-7 : DEBUG] FilterSecurityInterceptor : Public object - authentication not attempted
2016-10-06 15:37:20,420 [http-bio-8080-exec-7 : DEBUG] FilterChainProxy : /login?error=1 reached end of additional filter chain; proceeding with original chain

我只附上了相关的日志片段,因为 Debug模式产生了很多我认为不相关的日志,但是如果需要请告诉我,我可以添加更多。

我不确定我是否遗漏了这里的配置。有人会建议我在使用自定义失败处理程序时应该如何处理失败 url 重定向场景吗?

最佳答案

正如使用自定义登录表单的评论之一所述,即使登录页面与默认名称相同,即/login。查看 DefaultLoginPageGeneratingFilter 的代码,如果未使用失败处理程序,它只会设置注销和失败 url。我的工作 WebSecurityConfigurerAdapter 配置如下所示;

@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService)/*.passwordEncoder(new BCryptPasswordEncoder())*/;
}

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

     http.addFilterAfter(csrfTokenFilter, CsrfFilter.class);

     http.authorizeRequests().antMatchers("/rest/**").access("hasRole('ROLE_REST_USER')")
        .and().formLogin().loginPage("/login").usernameParameter("username").passwordParameter("password").permitAll()
        .successHandler(loginSuccessHandler)
        .failureHandler(authenticationFailureHandler).permitAll()
        .and().logout().invalidateHttpSession(true).addLogoutHandler(logoutSuccessHandler).permitAll()
        .and().exceptionHandling().accessDeniedPage("/403")
        .and().csrf();
}

关于java - 扩展 SimpleUrlAuthenticationFailureHandler 会产生 404 和 No mapping found 警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39899866/

相关文章:

java - Liquibase,本地 XSD 引用

java - 为什么 Spring Value 中的默认值不能防止 NULL 错误?

spring-boot - Spring Boot 2+ 无法 Autowiring 。 'UserDetailsService'的bean不止一个

java - servlet 和 jdbc 中未找到类异常

java - 在创建 Liferay 模块项目时无法使用 Gradle 执行构建

java - 正则表达式如何匹配字符串中不重复的子串?

java - 如何删除 Springfox Swagger 中操作的响应主体?

java - 为什么 equals() 中的顺序相反

spring - 在我们的 Spring Controller 中访问所有 @RequestHeader 键值作为 Map

java - 如何将 Java Web 应用程序转换为桌面 (.exe) 应用程序