SpringBoot整合Shiro
Posted laoash
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot整合Shiro相关的知识,希望对你有一定的参考价值。
SpringBoot整合Shiro
依赖:
<!-- 权限管理 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
如果使用redis来管理shiro时,需要添加依赖:
<!--redis管理shiro-->
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>2.8.24</version>
</dependency>
如果在thymeleaf中使用shiro,需要添加依赖:
<!--在thymeleaf使用shiro-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
1、从数据库读取数据,实现登录认证、授权
创建类继承AuthorizingRealm,重写doGetAuthorizationInfo方法和doGetAuthenticationInfo方法
public class MyShiroRealm extends AuthorizingRealm {
private final static Logger logger = LoggerFactory.getLogger(MyShiroRealm.class);
@Resource
private UserService userService;
@Resource
private RoleService roleService;
/**
* 授权
*
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
logger.info("-------->从数据库获取角色权限");
if (principals == null) {
return null;
}
//获取用户名
String userName = (String) principals.getPrimaryPrincipal();
//根据用户名获取角色
Role role = roleService.getRoleByUserName(userName);
//创建授权信息
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//获取角色拥有的权限
List<Permission> permissions = roleService.getPermissionByRoleId(role.getRoleId());
//授权
simpleAuthorizationInfo.addRole(role.getRoleName());
for (Permission permission : permissions) {
simpleAuthorizationInfo.addStringPermission(permission.getPermissionName());
}
return simpleAuthorizationInfo;
}
/**
* 登录认证
* 1.登录错误超过5次被锁定一个小时
* 2.一个小时之后次数恢复5次
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
logger.info("------>" + SecurityUtils.getSubject().getSession().getId());
//获取用户名密码
UsernamePasswordToken token1 = (UsernamePasswordToken) token;
String userName = token1.getUsername();
String password = String.valueOf(token1.getPassword());
//根据用户名获取对应的用户信息
User user = userService.getByUserName(userName);
if (user != null) {
if (user.getStatus() == 0) {
//账户被锁定
throw new LockedAccountException();
}
//用用户名当盐值
ByteSource credentialsSalt = ByteSource.Util.bytes(userName);
//加密
Md5Hash md5Hash = new Md5Hash(password, credentialsSalt, 1024);
Map<String, String> map = new HashMap<>(16);
map.put("username", userName);
map.put("password", md5Hash.toString());
//用户名,密码校验
User userInfo = userService.getByUserNameAndPassword(map);
if (userInfo == null) {
//密码错误
throw new IncorrectCredentialsException();
}
//修改最后登录时间
userInfo.setGmtModified(new Date());
userService.updateLastTime(userInfo);
return new SimpleAuthenticationInfo(userName, password, getName());
} else {
//未知账户
throw new UnknownAccountException();
}
}
}
2、shiro配置
使用redis缓存session
@Configuration
public class ShiroConfig {
private final static Logger logger = LoggerFactory.getLogger(ShiroConfig.class);
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.password}")
private String password;
/**
* 配置shiro过滤器
*
* @return
*/
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//设置默认登录的url
shiroFilterFactoryBean.setLoginUrl("/");
//设置成功之后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("");
//设置未授权界面,发现好像没用
shiroFilterFactoryBean.setUnauthorizedUrl("");
//自定义拦截器
//Map<String, Filter> filtersMap = new LinkedHashMap<String, Filter>();
//shiroFilterFactoryBean.setFilters(filtersMap);
//权限控制
Map<String, String> filterChainMap = new LinkedHashMap<String, String>();
//静态资源
filterChainMap.put("/css/**", "anon");
filterChainMap.put("/js/**", "anon");
filterChainMap.put("/images/**", "anon");
filterChainMap.put("/img/**", "anon");
filterChainMap.put("/**/*.do", "anon");
filterChainMap.put("/manage/login.html", "anon");
filterChainMap.put("/user/login", "anon");
//退出拦截
filterChainMap.put("/user/logout", "logout");
filterChainMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
return shiroFilterFactoryBean;
}
/**
* 自定义的Realm
*
* @return
*/
@Bean(name = "shiroRealm")
public MyShiroRealm shiroRealm() {
MyShiroRealm myShiroRealm = new MyShiroRealm();
myShiroRealm.setAuthorizationCachingEnabled(true);
return myShiroRealm;
}
/**
* 配置安全管理器
*
* @return
*/
@Bean
public SecurityManager securityManager(MyShiroRealm shiroRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//设置realm
securityManager.setRealm(shiroRealm);
// 自定义缓存实现 使用redis
securityManager.setCacheManager(cacheManager());
// 自定义session管理 使用redis
securityManager.setSessionManager(sessionManager());
return securityManager;
}
/**
* 配置shiro redisManager
* 使用的是shiro-redis开源插件
*
* @return
*/
private RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost(host);
redisManager.setPort(port);
// 配置缓存过期时间
redisManager.setExpire(1800);
redisManager.setTimeout(0);
return redisManager;
}
/**
* cacheManager 缓存 redis实现
* 使用的是shiro-redis开源插件
*
* @return
*/
private RedisCacheManager cacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
return redisCacheManager;
}
/**
* Session Manager
* 使用的是shiro-redis开源插件
*
* @return
*/
@Bean
public MySessionManager sessionManager() {
MySessionManager sessionManager = new MySessionManager();
sessionManager.setSessionDAO(redisSessionDAO());
return sessionManager;
}
/**
* RedisSessionDAO shiro sessionDao层的实现 通过redis
* 使用的是shiro-redis开源插件
*
* @return
*/
@Bean
public RedisSessionDAO redisSessionDAO() {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager());
return redisSessionDAO;
}
/**
* 开启Shiro的注解
*
* @return
*/
@Bean
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
/**
* Shiro生命周期处理器
*/
@Bean
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* 设置一个cookie的名称,防止session的id 重复
*/
@Bean
public SimpleCookie simpleCookie() {
return new SimpleCookie("REDISSESSION");
}
/**
* thymeleaf 使用 shiro
*
* @return
*/
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
}
3、解决每次访问创建session
创建类继承DefaultWebSessionManager,重写retrieveSession方法
public class MySessionManager extends DefaultWebSessionManager {
@Override
protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
//获取sessionId
Serializable sessionId = getSessionId(sessionKey);
ServletRequest request = null;
//判断类型
if (sessionKey instanceof WebSessionKey) {
//类型相同可以强转
request = ((WebSessionKey) sessionKey).getServletRequest();
}
//如果request,sessionId都不为空,从request中获取session
if (request != null && sessionId != null) {
Session session = (Session) request.getAttribute(sessionId.toString());
if (session != null) {
return session;
}
}
//检索会话
Session session = super.retrieveSession(sessionKey);
if (request != null && sessionId != null) {
request.setAttribute(sessionId.toString(), session);
}
return session;
}
}
以上是关于SpringBoot整合Shiro的主要内容,如果未能解决你的问题,请参考以下文章