Spring安全性返回String作为主体而不是登录失败时的UserDetails?
要么我错过了什么,要么它是如何工作的……
也就是说,我实现了UserDetailsService
和子类(下面的AppUser
)spring实用程序类User
(实现UserDetails
)。 如果重要,它会是这样的:
@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // try loading user by its name SystemUser user = null; try { user = this.sysUserService.getByUsername(username); if(user == null) throw new UsernameNotFoundException("User not found!"); } catch(Exception e) { throw new DataRetrievalFailureException( "Could not load user with username: " + username); } // load user rights, and create UserDetails instance UserDetails res = new AppUser(user, getUserAuthorities(user)); return res; }
然后我尝试使用这种方法实现帐户锁定:
public class LoginFailureEventListenter implements ApplicationListener { // rest omitted for brevity @Override public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event) { // ... SystemUser user = ((AppUser)event.getAuthentication().getPrincipal()).getSystemUser(); // cast exception - how is it possible to obtain String // instead of UserDetails object here ? // ... } }
但是,在尝试从提供的事件参数中获取主体对象时,我遇到了java.lang.ClassCastException
(主体对象的类型为String
)。 我的意思是,好的 – 我可以再次通过用户名加载我的SystemUser
来解决问题,但我没想到这个……
我认为即使是源文档也声明getPrincipal()
应该为此场景返回UserDetails
实例。
思考?
由于我们正在处理身份validation失败,因此事件中的Authentication
对象是提交给AuthenticationManager
(并且被拒绝)的对象。
在典型的场景中,这将是UsernamePasswordAuthenticationToken
,其中“principal”属性是提交的用户名。
AuthenticationManager
支持许多不同的身份validation机制,从它的角度来看,不能保证UserDetailsService
甚至参与身份validation。 它只知道身份validation令牌未被接受(存在exception)并且相应地发布事件。
替代选项是自定义正在使用的AuthenticationFailureHandler
或插入AuthenticationFailureHandler
(例如,如果您正在使用表单登录)并在那里执行额外的工作。