1.权限的管理
1.1 什么是权限管理
基本上涉及用户参与的系统都需要进行权限管理,权限管理是系统安全的范畴,权限管理可以按照安全规则或者安全策略控制用户访问及其被允许的资源。
权限管理包括身份认证 和授权 两部分,对用户需要访问的资源先进行身份认证,认证后确认用户是否有访问权限。
1.2 什么是身份认证
身份认证,就是判断一个用户是否为合法用户的处理过程。
1.3 什么是授权
授权,即访问控制,控制用户能访问哪些资源。
2.什么是Shiro
Shiro是apache旗下一个开源框架,将软件的安全认证功能抽取出来,实现用户身份认证,权限授权,加密,会话管理等功能,组成了一个通用的安全认证框架。
特点:
- 简单易用,学习成本低
- 提供易于理解的API
3.Shiro的核心架构
3.1 Subject(主体)
Subject即主体,外部应用与Subject交互,将当前用户作为操作主体,外部程序通过Subject进行认证授权,Subject通过SecurityManager安全管理器进行认证授权。
3.2 SecurityManager(安全管理器)
SecurityManager即安全管理器,对全部的Subject进行安全管理,是Shiro的核心。实质上SecurityManager 通过Realm 的Authenticator 进行认证,通过Authorizer 进行授权,通过SessionManager 进行会话管理 。
3.3 Authenticator(认证器)
Authenticator即认证器,对用户身份进行认证,Authenticator是一个接口,Shiro提供ModularRealmAuthenticator实现类,或者自定义认证器。
3.4 Authorizer(授权器)
Authorizer即授权器,用户通过机器授权,在访问功能时判断是否有此功能的操作权限。
3.5 Realm(领域)
Realm即领域,相当于DataSource数据源,SecurityManager进行安全认证需要通过Realm获取用户权限数据。
- 注意: 不要把Realm理解成从数据源取数据,在Realm中还有认证授权校验的相关的代码。
3.6 SessionManager(会话管理)
SessionManager即会话管理,不依赖于Web Session,可以使它实现单点登录。
3.7 SessionDAO(会话DAO)
SessionDAO即会话DAO,Session会话操作的一套接口,比如将Session存储到数据库。
3.8 CacheManager(缓存管理)
CacheManager即缓存管理,将用户权限数据存在缓存,可以提高性能。
3.9 Cryptogrphy(密码管理)
Cryptogrphy即密码管理,Shiro提供一套加密/解密组件,方便开发。比如提供常用的散列、加/解密等功能。
4.Shiro中的认证
4.1 认证
身份认证,就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令,查看是否与系统中存储的用户名和口令一致,判断用户身份是否正确。
4.2 Shiro中认证的关键对象
- Subject 主体
- 访问系统的用户,进行认证的都称为主体
- Principal 身份信息
- 是主体进行身份认证的标识,标识具有唯一性,一个主体可以有多个身份,但是必须有一个主身份
- Credential 凭证信息
- 只有主体知道的自己的安全信息
4.3 认证流程
4.4 认证的开发
1.创建项目并引入依赖
1 | <!--引入Shiro的相关依赖--> |
2.引入Shiro配置文件并加入如下配置
1 | # shiro.ini 假数据 |
3.开发认证代码
1 | public static void main(String[] args) { |
4.自定义认证和授权的Realm
认证:
- 最终执行用户名比较 SimpleAccountRealm
- doGetAuthenticationInfo 在这个方法中完成用户名校验
- 最终密码校验是在AuthenticatingRealm 中
- assertCredentialsMatch
总结:
对象 | 功能 | 方法 |
---|---|---|
AuthenticatingRealm | 认证Realm | doGetAuthenticationInfo |
AuthorizingRealm | 授权Realm | doGetAuthorizationInfo |
自定义Realm实现,将认证/授权数据的来源转为数据库
仅实现认证
1 | /** |
1 | /** |
MD5加密逻辑
注意: MD5不能调用setBytes() 方法去获取加密内容,必须使用构造器
1 | // MD5 |
MD5认证流程实现
将自定义Realm中的CredentialsMatcher凭证匹配器设置Hash凭证匹配器
1
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
HashCredentialsMatcher凭证器支持的算法很多,写上支持的算法名字即可
1
hashedCredentialsMatcher.setHashAlgorithmName("md5");
认证时加上
ByteSource.Util
类的bytes()方法 ( 随机盐的使用方法 )- 参数1:数据库用户名
- 参数2:md5密码密文
- 参数3:随机盐
- 参数4:Realm的名字
1
return new SimpleAuthenticationInfo("xiaochen","e5152ece30ac7ac598905ca5ea161acc", ByteSource.Util.bytes("sakdj*12"),this.getName());
1 | /** |
1 | /** |
5.Shiro中的授权
5.1 授权
授权,即访问控制,控制哪些主体可以访问哪些资源。
5.2 关键对象
授权可以理解为who对what进行how操作
- Who,即主体(Subject)
- What,即资源(Resource)
- How,即权限/许可(Permisssion)
5.3 授权流程
5.4 授权方式
基于角色的访问控制
RBAC基于角色的访问控制(Role-Based Access Control)是以角色为中心进行访问控制
1
2
3if(subject.hasRole("admin")){
//操作什么角色
}
基于资源的访问控制
RBAC基于资源的访问控制(Resource-Based Access Control)是以资源为中心进行访问控制
1
2
3
4if(subject.isPermission("user:create:*")){
//谁 ,拥有 什么样的权限,对 哪些资源
//对所有的用户具有创建权限
}
5.5 权限字符串
资源标识符:操作:资源实例标识符
- 用户创建权限: (user:create 或 user:create)
- 用户修改实例001的权限: (user:update:001)
- 用户实例001的所有权限: (user:*:001)
5.6 Shiro中授权编程的实现
编程式
1
2
3
4
5
6Subject subject=SecurityUtils.getSubject();
if(subject.hasRole("admin")){
//有权限
}else{
//没有权限
}注解式
1
2
3
4
public void hello(){
//有权限
}标签式
1
2
3
4
5<!--JSP-->
<shiro:hasRole name="admin">
<!--有权限-->
</shiro:hasRole>
<!--Themeleaf中需要额外集成-->
5.7 开发授权代码
1 | /** |
1 | /** |
6.SpringBoot整合实战
6.1 运行逻辑
6.2 导入依赖
1 | <dependency> |
6.3 常见过滤器
- 注意:shiro提供多个默认的过滤器,我们可以用这些过滤器来配置控制指定url的权限
配置缩写 | 对应的过滤器 | 功能 |
---|---|---|
anon | AnonymousFilter | 指定url可以匿名访问 |
authc | FormAuthenticationFilter | 指定url需要form表单登录,默认会从请求中获取username、password、rememberMe等参数并尝试登录,如果登录不了就会跳转到loginUrl配置的路径。我们也可以用这个过滤器做默认的登录逻辑,但是一般都是我们自己在控制器写登录逻辑的,自己写的话出错返回得到信息都可以定制。 |
authcBasic | BasicHttpAuthenticationFilter | 指定url需要basic |
logout | LogoutFilter | 登出过滤器,配置指定url就可以实现退出功能,非常方便 |
noSessionCreation | NoSessionCreationFilter | 禁止创建会话 |
perms | PermissionsAuthorizationFilter | 需要指定权限才能访问 |
port | PortFilter | 需要指定端口才能访问 |
rest | HttpMethodPermissionFilter | 将http请求方法转化成相应的动词来构造一个权限字符串,这个感觉意义不大 |
roles | RolesAuthorizationFilter | 需要指定角色才能访问 |
ssl | SslFilter | 需要https请求才能访问 |
user | UserFilter | 需要已登录或”记住我”的用户才能访问 |
6.4 配置文件
1 | spring: |
6.5 编辑代码
6.5.1 Shiro配置类
ShiroFilter
功能:负责拦截所有请求,将SecurityManger自动注入到ShiroFilter中
SecurityManager
功能:需要将Realm数据来源自动注入到SecurityManger中Realm
功能:创建自定义的Realm,配置密码凭证校验器、缓存、操作数据等
1 | /** |
6.5.2 自定义Realm
1 | public class CustomerRealm extends AuthorizingRealm { |
6.5.3 自定义缓存管理器
1 | public class RedisCacheManger implements CacheManager { |
6.5.4 配置Redis缓存
1 | public class RedisCache<k,v> implements Cache<k,v> { |
6.5.5 调用实现的方法
1 |
|