我正在尝试在spring身份验证服务器(spring security<5.0)中配置多个身份验证提供程序(主要和次要)。我知道用户将在主提供商或第二提供商上找到,而不会同时在这两个提供商上找到。因此,如果主提供者的身份验证失败,我想给出一个正确的消息。
根据“认证”方法文档:
返回:包含凭据的完全经过身份验证的对象。如果authenticationprovider无法支持对传递的身份验证对象的身份验证,则可能返回null。在这种情况下,将尝试下一个支持提供的身份验证类的authenticationprovider。
抛出:authenticationexception-如果身份验证失败。
基于此,我在主提供程序上实现了authenticate方法,如下所示(我将省略secondaryauthprovider实现):
//PrimaryAuthProvider.class
public Authentication authenticate(Authentication authentication) {
var user = authServices.getLdapUser(authentication.getName());
//log and let the next provider handle it
if (user == null) {
logServices.userNotFound(new LogServices.AuthFailure(authentication.getName()));
return null;
}
if (passwordMatches(authentication.getCredentials(), user.getStringPassword())) {
return authenticatedToken(user);
} else {
logServices.authFailure(new LogServices.AuthFailure(authentication.getName()));
throw new BadCredentialsException("Invalid password");
}
}
在websecurity内部,我还注入了我的提供者:
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(primaryAuthProvider);
auth.authenticationProvider(secondaryAuthProvider);
}
这将正确处理问题,如果:
用户告知正确的登录名/密码,无论供应商是谁。
无论密码是否正确,在主提供程序上都找不到用户。
如果在主提供程序上找到用户且其密码错误,将抛出badcredentialsexception,但服务器仍将委托给辅助提供程序,并且最终消息将为“user not found”,这会产生误导。
我认为badcredentialsexception将完成身份验证链并向客户机/用户报告,但事实似乎并非如此。
我错过什么了吗?
1条答案
按热度按时间xj3cbfub1#
好吧,我想起来了。
提供程序管理器是在我的服务器上使用的默认身份验证管理器。如果发生authenticationexception,它的身份验证方法实际上会委托给下一个提供程序:
我找到了两种方法。
第一个:如果身份验证失败,请在主提供程序上提供未经身份验证的令牌,并且不引发任何异常:
这样做的缺点是用英语显示默认消息。我需要在其他地方拦截异常,并用葡萄牙语抛出一个新的异常。
第二个(我希望使用):将我自己的authorizationmanager实现为providermanager的一个较小版本。此选项不会尝试捕获提供商启动的异常:
然后,在WebSecurity配置中:
这第二个需要多一点编码,但给了我更多的控制。