Java 处理Spring Security中出现的BadCredentialsException';s身份验证提供程序

Java 处理Spring Security中出现的BadCredentialsException';s身份验证提供程序,java,authentication,spring-security,exception-handling,Java,Authentication,Spring Security,Exception Handling,我正在使用SpringMVC和SpringSecurity开发一个web应用程序 我正在使用自定义登录和AuthenticationProvider,后者反过来使用UserDetailsService将登录表单中的数据与数据库中的数据进行匹配 我想在AuthenticationProvider中引发2个异常,第一个异常是当用户名不在数据库中时,另一个异常是当密码不同时 我想做的是在我的网页中显示throwned异常的错误消息(错误的用户名或密码),但我不知道在哪里使用catch块,因为登录流是由

我正在使用SpringMVC和SpringSecurity开发一个web应用程序

我正在使用自定义登录和AuthenticationProvider,后者反过来使用UserDetailsService将登录表单中的数据与数据库中的数据进行匹配

我想在AuthenticationProvider中引发2个异常,第一个异常是当用户名不在数据库中时,另一个异常是当密码不同时

我想做的是在我的网页中显示throwned异常的错误消息(错误的用户名或密码),但我不知道在哪里使用catch块,因为登录流是由Spring安全性管理的

AuthenticationProvider

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    CustomUserDetailsService userDetails;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = authentication.getCredentials().toString();

        Customer customer = userDetails.loadUserByUsername(username);

        if(customer == null) {
            throw new BadCredentialsException("Wrong username");
        }

        if(!password.equals(customer.getPassword())) {
            throw new BadCredentialsException("Wrong password");
        }

        List<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority(customer.getRole()));

        return new UsernamePasswordAuthenticationToken(customer, password, authorities);
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return clazz.equals(UsernamePasswordAuthenticationToken.class);
    }
}
@组件
公共类CustomAuthenticationProvider实现AuthenticationProvider{
@自动连线
CustomUserDetails服务用户详细信息;
@凌驾
公共身份验证(身份验证)引发AuthenticationException{
字符串username=authentication.getName();
字符串密码=authentication.getCredentials().toString();
Customer=userDetails.loadUserByUsername(用户名);
如果(客户==null){
抛出新的BadCredentialsException(“错误的用户名”);
}
如果(!password.equals(customer.getPassword())){
抛出新的BadCredentialsException(“错误密码”);
}
列表权限=新建ArrayList();
添加(新的SimpleGrantedAuthority(customer.getRole());
返回新的用户名PasswordAuthenticationToken(客户、密码、权限);
}
@凌驾
公共布尔支持(类clazz){
返回clazz.equals(UsernamePasswordAuthenticationToken.class);
}
}
登录页面

[...]
<div class="form">
    <h2>Login</h2>
    <form th:action="@{/login}" method="POST" th:object="${customer}">
        <input type="text" placeholder="Username" name="username" th:field="*{username}"/> 
        <input type="password" placeholder="Password" name="password" th:field="*{password}"/>
        <button type="submit">Login</button>
    </form>
</div>
[...]
[…]
登录
登录
[...]
spring security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.0.xsd">

    <http pattern="/resources/**" security="none" />

    <http auto-config="true" use-expressions="true">
        <intercept-url pattern="/user/**" access="hasRole('USER')" />
        <form-login authentication-failure-url="/login" login-page="/login"
            login-processing-url="/login" default-target-url="/user" />
        <logout invalidate-session="true" success-handler-ref="logoutSuccessHandler" />
    </http>

    <authentication-manager>
        <authentication-provider ref="customAuthenticationProvider" />
    </authentication-manager>
</beans:beans>

使用Thymeleaf时,您可以像下面这样“捕获”身份验证异常:

错误的用户名或密码

您可能可以使用标准的
DaoAuthenticationProvider
,而不是自定义类:

@Bean
公共DaoAuthenticationProvider customAuthenticationProvider()
{
DaoAuthenticationProvider=新的DaoAuthenticationProvider();
setUserDetailsService(userDetailsService);
provider.setHideUserNotFoundExceptions(false);
退货供应商;
}

请注意,通常不建议在身份验证失败时告诉系统中是否存在用户名。

正如我所见,他不会在CustomAuthenticationProvider中的UserDetails服务中抛出异常,而是在CustomAuthenticationProvider中抛出所有逻辑,他希望在provider中抛出不同的错误消息,那么,在他的案例中,怎样才能看到thymeleaf中的错误文本呢?