前言先贴一个项目地址 GitHub-Springboot-shiro-Redis
全文基于Maven进行管理
本文涉及范围
1.shiro在Springboot的共享Session配置
2.Shiro单用户登录的配置
3.Spring-data-jpa的部分不会赘述
个人学习研究,目前未在生产环境使用,有好的意见欢迎评论
共享Session的应用场景应用场景
当用户访问系统服务时,会经过负载均衡,根据配置策略的不同,同一客户端访问的最终服务器可能不是同一台,为了保证用户的Session状态连续,则需要集群内各业务服务器共享Session。
目录
1.Maven 依赖引入shiro-spring-boot-web-starter
2.Shiro 的基本配置
3.Maven 依赖引入 spring-boot-starter-data-redis
4.针对集群共享需要进行的Shiro 扩展
5.集群共享Session下的单用户登录
1.Maven 依赖引入shiro-spring-boot-web-starter
编辑pom.xml文件
org.apache.shiro
shiro-spring-boot-web-starter
1.4.2
2.Shiro 的基本配置
根据文档,我们为了实现shiro接管web应用的访问路径,仅需要实现一个自定义Realm并注入Spring即可
2.1 创建自定义CustomeRealm继承AuthorizingRealm
主要是实现2个继承的方法
AuthenticationInfo :登录验证 定义判断用户的登录信息是否正确
doGetAuthorizationInfo:授权方法 定义如何获取用户的角色和权限的逻辑,给shiro做权限判断
CustomeRealm.java
class CustomRealm extends AuthorizingRealm {
@Autowired
UserService userService //用户对象的管理服务类,提供CURD操作
@Autowired
AuthService authService //权限验证服务类,可根据用户获取相应role和permission
/*** 定义如何获取用户信息的业务逻辑,给shiro做登录* @param token 登录TOKEN,包含了用户账号密码* @return* @throws AuthenticationException*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//登录TOKEN,包含了用户账号密码 UsernamePasswordToken upToken = (UsernamePasswordToken) token;
String username = upToken.getUsername();
//下列多个判断可根据业务自行增删 // 判断用户名是否不存在,如果不存在抛出异常 if (username == null) {
throw new AccountException("Null usernames are not allowed by this realm.");
}
//通过用户名,从数据库中查询出用户信息 User user = userService.findUserByName(username);
//如果用户不存在,则抛出账号不存在异常,由控制器决定返回消息为账号或密码错误 if (user == null) {
throw new UnknownAccountException("No account found for admin [" + username + "]");
}
// 如果用户账号为锁定状态,则不予登录。 if (user.isLocked()) {
throw new LockedAccountException("Account [" + username + "] is locked.");
}
//如果账号超出有效期,则不予登录 if (user.isCredentialsExpired()) {
String msg = "The credentials for account [" + username + "] are expired";
throw new ExpiredCredentialsException(msg);
}
//查询用户的角色和权限存到SimpleAuthenticationInfo中,这样在其它地方 //SecurityUtils.getSubject().getPrincipal() 就能拿出用户的所有信息,包括角色和权限
/** 将用户权限和角色存入User对象*/
user.setRoles(new HashSet(["admin","teacher"]))
user.setPerms(new HashSet(["blog:read","blog:search"]))
//构造验证信息返回 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.password, getName())
return info
}
/*** 授权* 定义如何获取用户的角色和权限的逻辑,返回包含用户角色和许可信息* @param principals* @return*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//null usernames are invalid if (principals == null) {
throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
}
//获取当前用户对应的User对象 User user = (User) getAvailablePrincipal(principals);
//创建权限对象 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//设置用户角色(user.getRoles()是一个Set,【admin,student。。。】) info.setRoles(user.getRoles())
//设置用户许可(user.getPerms()是一个Set,【blog:read,blog:search。。。】) info.setStringPermissions(user.getPerms())
return info
}
}
2.2 将CustomeRealm注入Spring
1.首先将CustomeRealm 配置为Bean
2.然后将CustomeRealm注入到DefaultWebSecurityManager中
创建配置对象ShiroConfig.java
@Configuration
class ShiroConfig {
/*** 注入自定义权限验证对象*/
@Bean
public CustomRealm customRealm() {
CustomRealm realm = new CustomRealm();
return new CustomRealm();
}
/*** SecurityManager是Shiro框架的核心,典型的Facade模式