在Spring框架中显示自定义登录错误的问题

时间:2018-10-02 12:30:09

标签: java spring spring-security

上下文 这个例子来自一个使用Spring Security防止暴力认证尝试的教程,但是我有一个问题,因为我没有看到任何错误消息。问题出在CustomAuthenticationFailureHandler上,它覆盖了failureHandler。感谢您的帮助。

SecurityConfiguration

@Configuration
@EnableWebSecurity 
public class MyWebSecurity extends WebSecurityConfigurerAdapter {

private MyUserDetailsService myUserDetailsService;
@Autowired
private AuthenticationFailureHandler authenticationFailureHandler;

public MyWebSecurity(MyUserDetailsService myUserDetailsService) {
    this.myUserDetailsService = myUserDetailsService;
}


@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(myUserDetailsService).passwordEncoder(bCryptPasswordEncoder());
}

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

@Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() {
    return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}

private static final String[] PUBLIC_MATCHERS = { "/css/**", "/js/**", "/fonts/**", "/img`enter code here`/**", "/vendor/**","/pdf/**",
        "/webjars/**", "/rest/**","/user/rememberPassword**","/user/createNewPassword**","/user/accountActivation**","/user/registrationConfirm**"};

@Override
public void configure(WebSecurity web) throws Exception {
  web.ignoring().antMatchers(PUBLIC_MATCHERS);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    /*http
    .authorizeRequests()
    .anyRequest().permitAll();}*/

    http
     .authorizeRequests()
        .antMatchers("/user/create").hasAnyRole("SUPER")
        .antMatchers("/user/**").hasAnyRole("ADMIN","SUPER")
        .antMatchers("publications/**").hasAnyRole("ADMIN","SUPER")
        .anyRequest().authenticated()
        .and()
        .formLogin()
            .loginPage("/login").permitAll()
            .loginProcessingUrl("/app-login")
            .usernameParameter("username") 
            .passwordParameter("password")
            .defaultSuccessUrl("/home", true) 
            .failureUrl("/login?error=true")
             .failureHandler(authenticationFailureHandler)
            .and()
            .logout()
            .logoutUrl("/app-logout")
                .clearAuthentication(true)
                .logoutSuccessUrl("/login")
                .permitAll().
                and().exceptionHandling() 
             .accessDeniedHandler(accessDeniedHandler())
             .and().httpBasic();
    http
      .sessionManagement()
      .invalidSessionUrl("/login")
      .maximumSessions(1).sessionRegistry(sessionRegistry()).expiredUrl("/login");  
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
    return new BCryptPasswordEncoder();
}

@Bean
public AccessDeniedHandler accessDeniedHandler() {
    return new AccessDeniedHandler() {
        @Override
        public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
                AccessDeniedException e) throws IOException, ServletException {
            httpServletResponse.sendRedirect("/cites5/accessDenied");

        }
    };
}

}

Class AuthenticationFailureHandler:

@Component("authenticationFailureHandler")
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    @Autowired
    private MessageSource messages;

    @Autowired
    private LocaleResolver localeResolver;

    @Override
    public void onAuthenticationFailure(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException exception) throws IOException, ServletException {
        setDefaultFailureUrl("/login?error=true");

        super.onAuthenticationFailure(request, response, exception);

        final Locale locale = localeResolver.resolveLocale(request);

        String errorMessage = messages.getMessage("message.badCredentials", null, locale);

        if (exception.getMessage().equalsIgnoreCase("User is disabled")) {
            errorMessage = messages.getMessage("auth.message.disabled", null, locale);
        } else if (exception.getMessage().equalsIgnoreCase("User account has expired")) {
            errorMessage = messages.getMessage("auth.message.expired", null, locale);
        } else if (exception.getMessage().equalsIgnoreCase("blocked")) {
            errorMessage = messages.getMessage("auth.message.blocked", null, locale);
        }

        request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, errorMessage);
    }
}

登录页面:

<div class="card card-login mx-auto form-transparent">
                <div th:if="${param.error != null}" class="alert alert-danger" th:text="${session[SPRING_SECURITY_LAST_EXCEPTION]}">error</div>

                    <div class="card-body ">
                        <form id="myForm" novalidate="" th:action="@{/app-login}"
                            th:method="post" th:object="${user}">
                            <div th:if="${msg}" id="info">
                                <div id="alert" class="alert alert-info">
                                    <button type="button" class="close" data-dismiss="alert"
                                        aria-hidden="true">×</button>
                                    <span class="glyphicon glyphicon-info-sign"></span> <strong>Informacja!</strong>
                                    <hr class="message-inner-separator">
                                    <p th:text="${msg}"></p>
                                </div>
                            </div>

1 个答案:

答案 0 :(得分:0)

我们必须对CustomAuthenticationFailureHandler进行类似的实现。我们与您所做的不同之处在于,在您的 onAuthenticationFailure 方法中添加了以下行,以便重定向到我们的登录失败页面。

response.sendRedirect("/login/loginFailed/"+errorMessage);

现在我们将用户重定向到loginFailed url,我们需要将其映射到控制器。在本例中,我们创建了一个登录控制器。

@RequestMapping(value = "/loginFailed/{errorMessage}")
public String errorLogin(Model model,
                         @PathVariable("errorMessage") String errorMessage) {
    model.addAttribute("errorMessage", errorMessage);
    return "/login";
}

现在仅要将参数添加到我们的登录页面。我们也在使用Thymeleaf,因此我们进行了以下操作。

<div th:if="${errorMessage}" class="alert alert-error">
      <label th:text="${errorMessage}" class="error"></label>
</div>

希望有帮助。