authentication.getPrincipal()为什么总是返回username而不是UserDetails的实现类
关于这个问题在网上找了很多,有说需要实现UserDetailsService,也有说要改源码,感觉都不靠谱,决定自己解决问题。
getPrincipal是Authentication接口下的一个方法,而getPrincipal方法有以下几个实现
经过断点调试,发现走的UsernamePasswordAuthenticationToken类中的实现方法,但是这个方法实现只是简单返回了principal这个属性,看不出什么东西
既然是对象的属性,那么再找找这个类的构造方法,发现UsernamePasswordAuthenticationToken的构造方法有两个
继续排查这两个构造方法的引用情况,发现其中一个构造方法被我们使用到
问题到这里已经很明显了,大概率是我们自定义的权限验证出了问题,查看SecurityAuthenticationProvider的authenticate方法
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// 自定义的验证逻辑
final String username = String.valueOf(authentication.getPrincipal());
final String password = String.valueOf(authentication.getCredentials());
Set<GrantedAuthority> authorities = new HashSet<>();
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
UserEntity userEntity = new UserEntity();
userEntity.setUsername(username);
userEntity.setPassword(password);
userEntity.setAuthorities(authorities);
// 返回UsernamePasswordAuthenticationToken对象
return new UsernamePasswordAuthenticationToken(username, password, authorities);
}
关注返回的对象
return new UsernamePasswordAuthenticationToken(username, password, authorities);
所用的构造器传入的第一个参数是username,看上面的构造方法代码不难发现这就是principal属性的值,所以,只需要改为
return new UsernamePasswordAuthenticationToken(userEntity, password, authorities);
至此,问题解决。
总结
关注SecurityAuthenticationProvider的authenticate方法的返回值,你返回什么,authentication.getPrincipal()就得到什么,很合理!