上下文 这个例子来自一个使用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>
答案 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>
希望有帮助。