shiro 简介
shiro是apache的一个开源框架,而且呢是一个权限管理的框架,用于实现用户认证、用户授权。spring 中也有一个权限框架 spring security (原名Acegi),它和 spring 依赖过于紧密,没有 shiro 使用简单。shiro 不依赖于 spring,shiro 不仅可以实现 web应用的权限管理,还可以实现c/s系统,分布式系统权限管理,shiro属于轻量框架,越来越多企业项目开始使用shiro。使用shiro实现系统的权限 管理,有效提高开发效率,从而降低开发成本。
shiro 基本功能点
subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。security Manager:安全管理器,主体进行认证和授权都是通过securityManager进行。authenticator:认证器,主体进行认证最终通过authenticator进行的。 authorizer:授权器,主体进行授权最终通过authorizer进行的。
sessionManager:web应用中一般是用web容器对session进行管理,shiro也提供一套session管理的方式。SessionDao: 通过SessionDao管理session数据,针对个性化的session数据存储需要使用sessionDao。
cache Manager:缓存管理器,主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和ehcache整合对缓存数据进行管理。 Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储。 realm:域,领域,相当于数据源,通过realm存取认证、授权相关数据。
认证流程
- 构建SecurityManager环境
- 主体提交认证
- SecurityManager 处理
- 流转到 Authenticator 执行认证通过 Realm 获取相关的用户信息(获取验证数据进行验证)
授权流程
- 创建构建SecurityManager环境
- 主体提交授权认证
- SecurityManager 处理
- 流转到 Authorizor 授权器执行授权认证
- 通过 Realm 从数据库或配置文件获取角色权限数据返回给授权器,进行授权。
shiro使用流程
注:适用于基于redis缓存的token验证,redis存储用户角色与权限,获取用户信息(包含角色、权限、登录过期时间、主键id等等)
自定义配置安全域
- extends AuthorizingRealm
- 验证用户名/密码/验证 token 是否有效
- 从数据库获取用户的角色
- 根据角色获取用户权限
shiro核心配置——config
- 读reids缓存
- 自定义域
- 构建 SecurityManager环境
- 配置shiro过滤器,配置拦截哪些请求
- 开启shiro aop注解支持
实例代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
public class ShiroConfig {
/**
*自定义密码 校验
*@return com.yingxue.lesson.shiro.CustomHashedCredentialsMatcher
*/
public CustomHashedCredentialsMatcher customHashedCredentialsMatcher(){
return new CustomHashedCredentialsMatcher();
}
/**
*自定义域
*@return com.yingxue.lesson.shiro.CustomRealm
*@throws
*/
public CustomRealm customRealm(){
CustomRealm customRealm=new CustomRealm();
customRealm.setCredentialsMatcher(customHashedCredentialsMatcher());
return customRealm;
}
/**
*安全管理
*@return org.apache.shiro.mgt.SecurityManager
*@throws
*/
public SecurityManager securityManager(){
//构建 SecurityManager环境
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
//自定义 Realm
securityManager.setRealm(customRealm());
return securityManager;
}
/**
*shiro过滤器,配置拦截哪些请求
*@param securityManager
*@return org.apache.shiro.spring.web.ShiroFilterFactoryBean
*@throws
*/
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager);
//自定义拦截器限制并发人数,参考博客
LinkedHashMap<String, Filter> filtersMap = new LinkedHashMap<>();
//用来校验token
filtersMap.put("token", new CustomAccessControlFilter()); shiroFilterFactoryBean.setFilters(filtersMap);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("/api/user/login", "anon");
//放开swagger-ui地址
filterChainDefinitionMap.put("/swagger/**", "anon");
filterChainDefinitionMap.put("/v2/api-docs", "anon");
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/swagger-resources/**", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");
filterChainDefinitionMap.put("/favicon.ico", "anon");
filterChainDefinitionMap.put("/captcha.jpg", "anon");
filterChainDefinitionMap.put("/csrf","anon");
filterChainDefinitionMap.put("/**","token,authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
*开启shiro aop注解支持.
*使用代理方式;所以需要开启代码支持;
*@param securityManager
*@return org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
*@throws
*/
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = newDefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
}
shiro注解控制请求调用与前端权限控制可见性
后端controller层shiro注解使用:
实例代码:
拥有sys:user:list权限的角色才能调用这个请求1
2
3
4
5
6
7
8"/users") (
"分页查询用户接口") (value =
"sys:user:list") (
public DataResult<PageVO<SysUser>> pageInfo( UserPageReqVO vo){
DataResult result=DataResult.success();
result.setData(userService.pageInfo(vo));
return result;
}
前端控制不同角色按钮元素可见性:
拥有sys:log:delete权限的角色才能看到使用这个按钮1
2
3
4
5
6
7<script type="text/html" id="toolbar">
<div class="layui-btn-group">
<button type="button" class="layui-btn" lay-event="batchDelLog" shiro:hasPermission="sys:log:delete">
<i class="layui-icon"></i> 批量删除
</button>
</div>
</script>
...
...
This is copyright.