security 的loadUserByUsername这个方法重写的问题
在使用security 做登录授权的时候,有一个接口UserDetailsService,通过实现该接口可以重写loadUserByUsername做用户校验,但是有个问题就是,当用户输入的账号不存在,怎么提示信息给前端,貌似只有输入用户密码错误框架才会返回:
{
"error": "invalid_grant",
"error_description": "用户名或密码错误"
}
如果
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 首先判断username是否存在
// 通过传进来的 username 去数据库查找用户信息,这里模拟
// User userInfo = userService.findUserByUserName(username);
if(userInfo == null){
return null; // 返回null 直接报500错误,怎么才能返回"用户名或密码错误"的提示,
}
// String userPasswordDb = userInfo.getPassword();
//Integer userId = userInfo.getId();
// 线上环境应该通过用户名查询数据库获取用户加密后的密码
String userPasswordDb = passwordEncoder.encode("123456");
// 根据用户名查询出来的用户角色权限列表
String permissions = "sys_user_edit,sys_user_del,sys_user_add";
CpmsUser userDetails = new CpmsUser(userId,username,userPasswordDb,AuthorityUtils.commaSeparatedStringToAuthorityList(permissions));
return userDetails;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,在不为security加入自定义过滤器的前提下,只能给出:
用户名或密码错误
的提示,没有办法细化到:用户名错了
或是密码错了
的提示。其次,如果只是想使
loadUserByUsername
返回类似用户名或密码错误
的提示,我认同楼上的方法,直接抛出异常即可:此时,前台将得到了一个401错误。表示:用户名或密码错误。
我简单说下为什么返回null会发生500,而抛出
UsernameNotFoundException
则会返回401.在
AbstractUserDetailsAuthenticationProvider
中有这么几行核心代码:然后另一个核心文件:
DaoAuthenticationProvider
中有这么几行核心代码:最后,在
BasicAuthenticationFilter
又有这么几行代码:最后再说一下为什么我们无法分辨出是:用户名不存在或密码错误。
在
DaoAuthenticationProvider
有以下几行是验证密码是否正确的:如上所示:如果密码未匹配成功,同样会抛出BadCredentialsException异常。既然用户名不存在与密码错误同样抛出的是BadCredentialsException异常,而Spring Security处理BadCredentialsException的方法又是统一的,所以得到401实际上只能代表接收到了BadCredentialsException异常,而该异常是由用户名错误引起的,或是由密码错误引起的,就无从得知了。
总结:Spring Security是个相对复杂的工程,水平有限,相信也没能讲明白,取其精华去其糟粕吧。
throw new UsernameNotFoundException();
原因.不抛出springsecurity系列的异常,比如UsernameNotFoundException,BadCredentialsException,CredentialsException等异常。否则会在springsecurity里统一成“认证失败"的异常信息,就无法区分用户不存在,密码错误,还是用户状态不对的情况。
解决办法:
1.我抛的是空指针异常,上层捕获,返回前端用户不存在,然后密码错误是在DaoAuthenticationProvider的自定义子类方法中抛出new BadCredentialsException("密码不正确!")。
2.你当然可以抛出自定义一系列异常,也能达到目的。