前序:我认为这种不叫做单点登录(本文不做详细配置流程)
一、预览
二、实现步骤
1、登录LoginController
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
return R.ok();
} catch (AuthenticationException e) {
return R.error("用户或密码错误");
}
简而言之,就是生成token扔给subject.login就行了,如果正确执行,就表示登录成功,如果抛出异常,就说明登录失败。
2、用户信息验证
public class UserRealm extends AuthorizingRealm
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();
Map<String, Object> map = new HashMap<>(16);
map.put("username", username);
String password = new String((char[]) token.getCredentials());
UserDao userMapper = ApplicationContextRegister.getBean(UserDao.class);
// 查询用户信息
UserDO user = userMapper.list(map).get(0);
// 账号不存在
if (user == null) {
throw new UnknownAccountException("账号或密码不正确");
}
// 密码错误
if (!password.equals(user.getPassword())) {
throw new IncorrectCredentialsException("账号或密码不正确");
}
// 账号锁定
if (user.getStatus() == 0) {
throw new LockedAccountException("账号已被锁定,请联系管理员");
}
//处理session
Collection<Session> sessions = sessionDAO.getActiveSessions();//获取当前已登录的用户session列表
for(Session session:sessions){
//清除该用户以前登录时保存的session
Object obj =session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
SimplePrincipalCollection coll = (SimplePrincipalCollection) obj;
if(coll !=null){
UserDO userddo = (UserDO)coll.getPrimaryPrincipal();
if(username.equals(userddo.getUsername())){
sessionDAO.delete(session);
}
}
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
return info;
}
对于单个用户来说,当其通过信息验证和写入新的session之间将旧的session去除掉,就可以写入新的session。
三、shiro流程简谈
详细介绍请戳官网此处进行简单的翻译介绍。