SecurityConfig配置文件
定义身份认证接口·,在登录的时候进行验证处理
其中,bCryptPasswordEncoder引用PasswordEncoder接口,只有两个核心方法
//输入明文密码,对密码加密
String encode(CharSequence rawPassword);
//明文密码 和 加密后的数据库密码 是否匹配
boolean matches(CharSequence rawPassword, String encodedPassword);
配置好配置文件之后,正式进入登录流程
SysLoginController中使用SysLoginService
完整代码如下
public String login(String username, String password, String code, String uuid)
{
...
...
// 用户验证
Authentication authentication = null;
try
{
// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(username, password));
}
catch (Exception e)
{
if (e instanceof BadCredentialsException)//密码不匹配,就会抛出这个异常
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
throw new UserPasswordNotMatchException();//这时候我们要定义新的自定义异常UserPasswordNotMatchException
}
else
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
throw new CustomException(e.getMessage());
}
}
...
...
其中authenticationManager.authenticate()方法会调用UserDetailsServiceImpl
如果密码不匹配,则抛出以下异常,UserPasswordNotMatchException是自定义的异常类
所有完成后,要获取用户信息,就要使用authentication.getPrincipal();
并存到缓存当中
关于UserDetailsServiceImpl
UserDetailsServiceImpl类需要继承专用接口UserDetailsService,才能被SpringSecurity识别
在这个类中,创建一个登陆用户createLoginUser,
需要用户信息,以及相应权限
返回值是UserDetails,所以loginUser也需要继承专用接口UserDetails,才能被SpringSecurity识别
关于LoginUser
LoginUser继承UserDetail
UserDetail是SpringSecutiry的接口,需要调用Authentication才能获取相关信息
所以,SysLoginService里的login方法
要获取用户信息,就要使用authentication.getPrincipal();
principal定义
principal代表什么那?如果阅读官方文档或者源码你会得到如下的定义:
解释:
1)可以是uuid
2)数据库中的主键
3)LDAP UUID或静态DN
4)在所有用户帐户中唯一的字符串用户名。
也就是说这个值必须是唯一的。也可以是邮箱、身份证等值。
UserDetailsServiceImpl的实现
话不多说,附上完整代码
@Service
public class UserDetailsServiceImpl implements UserDetailsService
{
private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
@Autowired
private ISysUserService userService;
@Autowired
private SysPermissionService permissionService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
SysUser user = userService.selectUserByUserName(username);
if (StringUtils.isNull(user))
{
log.info("登录用户:{} 不存在.", username);
throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
}
else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
{
log.info("登录用户:{} 已被删除.", username);
throw new BaseException("对不起,您的账号:" + username + " 已被删除");
}
else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
{
log.info("登录用户:{} 已被停用.", username);
throw new BaseException("对不起,您的账号:" + username + " 已停用");
}
return createLoginUser(user);
}
public UserDetails createLoginUser(SysUser user)
{
return new LoginUser(user, permissionService.getMenuPermission(user));//获取用户的菜单权限
}
}
可见,需要继承专用接口UserDetailsService,才能被SpringSecurity识别
创建user时,最重要的是管理权限。
permissionService.getMenuPermission(user)里描述了如何管理
需要借助到SysPermissionService中的方法。
再进到下一service层中,selectMenuPermsByUserId,根据用户ID查询权限,并用“,”隔开
再进到Mapper层中,使用mybatis查询数据库得到相应权限。