一、pom.xml引入jar包
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
二、加入shiro配置类:ShiroConfig.java
package com.example.demo.shiro;
import java.util.HashMap;
import java.util.Map;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.WebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
@Configuration
public class ShiroConfig {
@Value("${redis.host}")
private String redis_host;
@Value("${redis.port}")
private int redis_port;
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
defaultAAP.setProxyTargetClass(true);
return defaultAAP;
}
// cacheManager 缓存 redis实现 使用的是shiro-redis开源插件
public RedisCacheManager cacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
return redisCacheManager;
}
// 配置shiro redisManager 使用的是shiro-redis开源插件
public RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost(redis_host);
redisManager.setPort(redis_port);
redisManager.setExpire(1800);// 配置缓存过期时间 30分钟
redisManager.setTimeout(0);
// redisManager.setPassword(password);
return redisManager;
}
// SessionManager 使用的是shiro-redis开源插件
@Bean
public DefaultWebSessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
// 重定向url去除jssessionid
sessionManager.setSessionIdUrlRewritingEnabled(false);
sessionManager.setSessionDAO(redisSessionDAO());
return sessionManager;
}
// RedisSessionDAO shiro sessionDao层的实现 通过redis 使用的是shiro-redis开源插件
@Bean
public RedisSessionDAO redisSessionDAO() {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager());
return redisSessionDAO;
}
// 用于thymeleaf模板使用shiro标签
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
// 将自己的验证方式加入容器
@Bean
public CustomRealm myShiroRealm() {
return new CustomRealm();
}
// 加入缓存,防止doGetAuthorizationInfo执行两次
@Bean
public EhCacheManager getCache() {
return new EhCacheManager();
}
// 权限管理配置
@Bean
public WebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm
securityManager.setRealm(myShiroRealm());
// 设置普通缓存
// securityManager.setCacheManager(getCache());
// 自定义缓存实现 使用redis
securityManager.setCacheManager(cacheManager());
// 自定义session管理 使用redis
securityManager.setSessionManager(sessionManager());
return securityManager;
}
// 过滤器,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(WebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 登录
shiroFilterFactoryBean.setLoginUrl("/user/login");
// 首页
shiroFilterFactoryBean.setSuccessUrl("/getuser/1");
// 错误页面,认证不通过跳转
shiroFilterFactoryBean.setUnauthorizedUrl("/user/error");
Map<String, String> map = new HashMap<>();
// 登出
map.put("/user/logout", "logout");
// 忽略地址
map.put("/favicon.ico", "anon");
map.put("/user/login", "anon");
map.put("/user/dologin", "anon");
// 对所有用户认证
map.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(WebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
三、加入shiro自定义权限配置类:CustomRealm.java
package com.example.demo.shiro;
import java.util.HashMap;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import com.example.demo.mapper.UserMapper;
public class CustomRealm extends AuthorizingRealm {
@Autowired
private UserMapper userMapper;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// 获取登录用户名
String name = (String) principalCollection.getPrimaryPrincipal();
// 查询用户名称
HashMap<String, Object> user = userMapper.findByName(name);
// 添加角色和权限
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
// for (Role role : user.getRoles()) {
// // 添加角色
// simpleAuthorizationInfo.addRole(role.getRoleName());
// // 添加权限
// for (Permissions permissions : role.getPermissions()) {
// simpleAuthorizationInfo.addStringPermission(permissions.getPermissionsName());
// }
// }
// 添加角色
simpleAuthorizationInfo.addRole("admin");
// 添加权限
simpleAuthorizationInfo.addStringPermission("add");
simpleAuthorizationInfo.addStringPermission("query");
return simpleAuthorizationInfo;
}
/**
* @MethodName doGetAuthenticationInfo
* @Description 认证配置类
* @Param [authenticationToken]
* @Return AuthenticationInfo
* @Author WangShiLin
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
if (StringUtils.isEmpty(authenticationToken.getPrincipal())) {
return null;
}
// 获取用户信息
String name = authenticationToken.getPrincipal().toString();
// 查询用户名称
HashMap<String, Object> user = userMapper.findByName(name);
if (user == null) {
// 这里返回后会报出对应异常
return null;
} else {
// 这里验证authenticationToken和simpleAuthenticationInfo的信息
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.get("password").toString(), getName());
return simpleAuthenticationInfo;
}
}
}
四、基本使用方法
1.登录方法
@RequestMapping("/user/dologin")
@ResponseBody
public String dologin(@RequestParam(value = "name") String name, @RequestParam(value = "password") String password) {
if (StringUtils.isEmpty(name) || StringUtils.isEmpty(password)) {
return "请输入用户名和密码!";
}
// 用户认证信息
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(name, password);
try {
// 进行验证,这里可以捕获异常,然后返回对应信息
subject.login(usernamePasswordToken);
// subject.checkRole("admin");
// subject.checkPermissions("query", "add");
} catch (UnknownAccountException e) {
return "用户名不存在!";
} catch (IncorrectCredentialsException e) {
return "密码不正确!";
} catch (ExpiredCredentialsException e) {
return "密码过期!";
} catch (LockedAccountException e) {
return "用户被锁定!";
} catch (DisabledAccountException e) {
return "用户被禁用!";
} catch (ExcessiveAttemptsException e) {
return "登录失败次数过多!";
} catch (AuthenticationException e) {
return "登录出现未知错误!";
} catch (AuthorizationException e) {
return "没有权限!";
}
return "login success";
}
2.控制器控制权限方法
@RequiresRoles("admin")
@RequestMapping("/admin")
@ResponseBody
public String admin() {
return "admin success!";
}
@RequiresPermissions("query")
@RequestMapping("/query")
@ResponseBody
public String index() {
return "index success!";
}
3.Thymeleaf页面权限控制方法
权限
<shiro:hasPermission name="add">增加</shiro:hasPermission>
<shiro:hasPermission name="update">修改</shiro:hasPermission>
<shiro:hasPermission name="delete">删除</shiro:hasPermission>
<shiro:hasPermission name="query">查询</shiro:hasPermission>
<br>
角色
<shiro:hasRole name="admin">admin</shiro:hasRole>
<shiro:hasRole name="hr">hr</shiro:hasRole>
4.全局异常捕捉
@ControllerAdvice
public class ExceptionFilter {
@ExceptionHandler
@ResponseBody
public String ErrorHandler(Exception e) {
return "未知异常!原因是" + e;
}
@ExceptionHandler
@ResponseBody
public String ErrorHandler(AuthorizationException e) {
return "没有通过权限验证!";
}
}