在使用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;
}
首先,在不为security加入自定义过滤器的前提下,只能给出:
用户名或密码错误
的提示,没有办法细化到:用户名错了
或是密码错了
的提示。其次,如果只是想使
loadUserByUsername
返回类似用户名或密码错误
的提示,我认同楼上的方法,直接抛出异常即可:此时,前台将得到了一个401错误。表示:用户名或密码错误。
我简单说下为什么返回null会发生500,而抛出
UsernameNotFoundException
则会返回401.在
AbstractUserDetailsAuthenticationProvider
中有这么几行核心代码:然后另一个核心文件:
DaoAuthenticationProvider
中有这么几行核心代码:最后,在
BasicAuthenticationFilter
又有这么几行代码:最后再说一下为什么我们无法分辨出是:用户名不存在或密码错误。
在
DaoAuthenticationProvider
有以下几行是验证密码是否正确的:如上所示:如果密码未匹配成功,同样会抛出BadCredentialsException异常。既然用户名不存在与密码错误同样抛出的是BadCredentialsException异常,而Spring Security处理BadCredentialsException的方法又是统一的,所以得到401实际上只能代表接收到了BadCredentialsException异常,而该异常是由用户名错误引起的,或是由密码错误引起的,就无从得知了。
总结:Spring Security是个相对复杂的工程,水平有限,相信也没能讲明白,取其精华去其糟粕吧。