最近在集成sping security 到spring boot中,看到大部分登陆验证的代码都这么写
@Service
public class CustomUserService implements UserDetailsService { //自定义UserDetailsService 接口
@Autowired
UserDao userDao;
@Autowired
PermissionDao permissionDao;
public UserDetails loadUserByUsername(String username) {
SysUser user = userDao.findByUserName(username);
if (user != null) {
List<Permission> permissions = permissionDao.findByAdminUserId(user.getId());
List<GrantedAuthority> grantedAuthorities = new ArrayList <>();
for (Permission permission : permissions) {
if (permission != null && permission.getName()!=null) {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getName());
grantedAuthorities.add(grantedAuthority);
}
}
return new User(user.getUsername(), user.getPassword(), grantedAuthorities);
} else {
throw new UsernameNotFoundException("admin: " + username + " do not exist!");
}
}
}
然后配置那时的代码为:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(urlUserService).passwordEncoder(new PasswordEncoder() {
@Override
public String encode(CharSequence rawPassword) {
return MD5Util.encode((String) rawPassword);
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encodedPassword.equals(MD5Util.encode((String) rawPassword));
}
});
}
看到以上代码,我就有个疑问了。 loadUserByUsername是为什么要把用户的权限也获取了呢,如果密码不正确,那获取的权限也没有用,浪费性能。 个人调试了一下代码,发现登陆验证时,确实会调用到loadUserByUsername。 那怎么办呢?如何解决。 经查,解决办法如下; 1.不使用UserDetailsService,改为使用AbstractUserDetailsAuthenticationProvider 示例代码如下:
public class MucAppAuthenticationProvider extends
AbstractUserDetailsAuthenticationProvider {
private static Logger logger = LoggerFactory.getLogger(AbstractUserDetailsAuthenticationProvider.class);
@Autowired
SecurityUserService securityUserService;
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
//如果想做点额外的检查,可以在这个方法里处理,校验不通时,直接抛异常即可
}
@Override
protected UserDetails retrieveUser(String username,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
//获取用户权限或密码校验
return loadUserDetail(username);
}
}
2.配置WebSecurityConfigurer改为如下:
@Bean
AppAuthenticationProvider appAuthenticationProvider() { // 注册UserDetailsService 的bean
return new AppAuthenticationProvider();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(appAuthenticationProvider());
}
经测试,登陆验证没有发现任何问题