Shiro
2021-07-01 07:33:38 29 举报
AI智能生成
Shiro学习框架
作者其他创作
大纲/内容
权限管理
什么是权限管理
基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴
权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。
权限包括用户认证和授权两部分。对于需要访问控制的资源用户首先经过身份认证,认证通过后用户具有该资源的访问权限方可访问。
用户身份认证
概念
身份认证,就是判断一个用户是否是合法用户的一个过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令,看是否与系统中存储的该用户的用户名和口令一致,来判断用户是否正确。还有其他的身份认证方式,例如指纹、刷卡等。
用户密码身份认证流程
分支主题
流程图关键对象
Subject:主体
访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体。
Principal:身份信息
是主体(subject)进行身份认证的标识,标识具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但必须有一个主身份(Primary Principal)
credential:凭证信息
是只有主体自己知道的安全信息,如密码、证书等。
用户授权
概念
授权,即访问控制,控制谁能访问那些资源。主体进行身份认证后需要分配权限后方可访问系统资源,对于某些资源没有权限是无法访问的。
授权流程
分支主题
流程图关键对象
授权可简单理解为who对what(which)进行how操作:
- Who,即主体(Subject),主体需要访问系统中的资源。
- What,即资源(Resource),如系统菜单、页面、按钮、类方法、系统商品信息等。
-How,权限/许可(Permission),规定了主体对资源操作的许可,权限离开资源没有意义,如用户查询权限、用户添加权限、某个类方法的调用权限、编号001的用户修改权限,通过权限可知主体对那些资源都有哪些操作。
权限
粗粒度
粗粒度权限是指对资源类型的权限
细粒度
细粒度权限是对资源实例的权限。
主体、资源、权限关系如下图
分支主题
权限模型
子主题 1
分支主题
子主题 2
分支主题
权限分配
对主体进行权限分配,主体只允许对分配的权限范围内的资源进行操作。
权限分配的数据通常都需要进行持久化。
权限控制
基于角色的访问控制
RBAC基于角色的访问控制(Role-Based Access Control)是以角色为中心进行访问控制
缺点
以角色进行访问 控制粒度较粗。
系统扩展性较差。
基于资源的访问控制
RBAC基于资源的访问控制(Resouce-Based Access Control)是以资源为中心进行访问控制
优点
系统设计时定义好查询工资的权限标识。
系统可扩展性强
访问控制流程
分支主题
权限管理解决方案
粗颗粒度和细颗粒度
对资源类型的管理称为粗颗粒度权限管理,既只控制到菜单、按钮、方法,粗颗粒度的例子比如:用户具有用户管理的权限,具有导出订单的权限。
对资源实例的控制称为细颗粒度权限管理,既控制到数据级别,比如:用户只允许查看本部门员工的信息,用户只允许导出自己创建的订单。
对于粗颗粒度的权限管理可以很容易做到系统架构级别的功能,即系统功能操作使用统一的粗颗粒度的权限管理。
对于细颗粒度的权限管理不建议做成系统架构级别的功能,因为对数据级别的控制是系统的业务需求,随着业务需求的改变业务功能变化的可能性很大,建议对数据级别的权限控制在业务层个性化开发,比如:用户只允许修改自己创建的商品信息,可以在service接口添加校验实现,service接口需要传入当前操作人的标识,与商品创建人的标识对比,如果不一致则拒绝修改。
基于url拦截
基于url拦截是企业中常用的权限管理方法
实现思路
将系统操作的每个url配置在权限表中,将权限对应到角色,将角色分配给用户,用户访问系统功能通过Filter进行过滤,Filter获取用户访问的url,只要访问的url是用户分配角色中的url则放行继续访问。
流程如下图
分支主题
使用权限管理框架
shiro介绍
什么是shiro
Apache Shiro(日语“堡垒(Castle)”的意思)是一个强大易用的Java安全框架,
提供了认证、授权、加密和会话管理功能,可为任何应用提供安全保障 - 从命令行应用、移动应用到大型网络及企业应用
为什么需要学习shiro
shiro已经将安全认证相关的功能抽取出来组成一个框架,使用shiro就可以非常快速的完成认证、授权等功能的开发,降低系统开发成本。
shiro使用广泛,shiro可以运行在web应用、非web应用、集群分布式应用中越来越多的用户开始使用shiro。
java领域中spring security也是一个开源的权限管理框架,但是spring security依赖spring运行,
而shiro就相对独立,最主要因为shiro使用简单、灵活。
shiro架构
整体架构图
分支主题
架构图分析
shiro的jar包
shiro-core.jar是必选的
还提供了与web整合的shiro-web
与spring整合的shiro-spring
与任务调度quartz整合的shiro-quartz
各jar包的maven坐标
shiro认证
认证流程
分支主题
入门程序(用户登录和退出)
1、创建Java项目
2、加入shiro的jar包以及依赖包
分支主题
3、log4j.properties日志文件配置
log4j.rootLogger=debug, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
4、eclipse中ini文件打开方式配置
分支主题
5、创建ini配置文件
在classpath路径下创建shiro-first.ini文件,文件内容是测试用户的账号和密码
内容如下:
6、认证代码
7、认证执行流程
8、常见的异常
UnknownAccountException (账号不存在)
IncorrectCredentialsException (输入密码错误)
DisabledAccountException(帐号被禁用)
LockedAccountException(帐号被锁定)
ExcessiveAttemptsException(登录失败次数过多)
ExpiredCredentialsException(凭证过期)等
自定义Realm
说明
上面的程序使用的是Shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息。
但是实际情况中大部分情况下是从数据库中获取用户信息,所以需要自定义realm。
Shiro中Realm
CachingRealm负责缓存管理
AuthenticatingRealm负责认证
AuthorizingRealm负责授权
通常自定义的Realm继承AuthorizingRealm。
自定义Realm案例
代码
ini配置文件
测试代码
散列算法
说明
散列算法一般用于生成一段文本的摘要信息,散列算法不可逆,也就是将内容生成摘要,但是反过来通过摘要生成内容是不可以的。
散列算法常用于对密码进行散列,常用的散列算法有MD5、SHA。
一般散列算法需要提供一个salt(盐)与原始内容生成摘要,这样做的目的是为了安全性。
例子
在realm中使用散列算法
实际系统中是将盐和散列后的值存储在数据库中,自定义realm从数据库取出盐和加密后的值由shiro完成密码校验。
自定义支持散列的realm
支持散列的realm配置
测试代码
shiro授权
授权流程
分支主题
授权方式
Shiro支持三种方式的授权:
编程式:通过写if/else授权代码块完成。
注解式:通过在执行的Java方法上放置相应的注解完成。
JSP标签:在Jsp页面通过相应的标签完成。
授权测试
创建ini配置文件
在classpath路径下创建shiro-permission.ini文件,内容如下
在ini文件中用户、角色、权限的配置规则是:
用户名=密码,角色1,角色2 、
角色=权限1,权限2。
首先根据用户找角色,再根据角色找权限,角色是权限集合。
权限字符串规则
权限字符串的规则是:”资源标识符:操作:资源实例标识符”
意思是对哪个资源的哪个实例具有什么操作,
”:”是资源/操作/实例的分割符,权限字符串也可以使用*通配符。
例子:
用户创建权限:user:create或user:create:*
用户修改实例001的权限:user:update:001
用户实例001的所有权限:user:*:001
测试代码
基于角色的授权
代码
对应的check方法:
基于资源授权
自定义授权realm
realm代码
shiro-realm.ini文件
测试代码
同上边的授权测试代码,注意修改ini地址为shiro-realm.ini。
授权执行流程
1、 执行subject.isPermitted(“user:create”)
2、 securityManager通过ModularRealmAuthorizer进行授权
3、 ModularRealmAuthorizer调用realm获取权限信息
4、 ModularRealmAuthorizer再通过permissionResolver解析权限字符串,校验是否匹配
shiro和web项目整合
将shiro整合到web应用中
数据库脚本
添加shiro的jar包
shiro-core相关的jar包
与web整合的 shiro-web-1.3.2.jar
与spring整合的 shiro-spring-1.3.2.jar
与ehcache整合的 shiro-ehcache-1.3.2.jar
在web.xml中配置shiro的filter
新建spring-shiro.xml文件
测试是否整合成功
在界面输入CustomRealm 代码中的账号为 zhangsan 密码为 123 可以进入欢迎页面。
登录
原理
修改登录页面
修改controller类
修改认证拦截器
将所有请求都改为需要认证才能访问的。
验证登录功能
退出
退出不需要我们自己实现,只要去访问一个退出的url(该url是可以不存在的)即可,由LogoutFilter filter处理,清除session。
在spring-shiro.xml配置logoutFilter
删除原来的退出方法。
认证信息在页面展现,也就是显示菜单
修改realm代码
修改FirstAction中的first方法
shiro的过滤器
常用过滤器
分支主题
过滤器的介绍和作用:
web项目中认证
实现方式
修改CustomRealm 的 doGetAuthenticationInfo 方法,从数据库中获取用户信息,CustomRealm 返回查询到的用户信息,包括(加密后的密码字符串和salt以及上文中的菜单)。
修改 doGetAuthenticationInfo 方法
设置凭证匹配器
在数据库存储的是MD5散列值,在自定义的realm中需要自定义设置散列算法以及散列次数。这里和前面介绍的散列认证的配置方式类似。
验证认证功能
数据库存在两条用户数据
分支主题
web项目中授权
实现方式
修改 CustomRealm 中的 doGetAuthorizationInfo 方法从数据库中查询授权信息。
修改 doGetAuthorizationInfo 方法
controller类的AOP支持
在ItemsController类方法上添加注解
jsp标签授权
在jsp页面添加shiro taglib
<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>
shiro包括的jsp标签
分支主题
修改itemsList.jsp文件
授权测试
当调用controller的一个方法时,由于该方法加了@RequiresPermissions("item:query") 注解,shiro会调用realm获取数据库中的权限信息,看 item:query 是否在权限数据中存在,如果不存在就拒绝访问,如果存在就授权通过
当展现一个jsp页面时,页面中如果遇到 <shiro:hasPermission name="item:update"> 标签,shiro调用realm获取数据库中的权限信息,看 item:update 是否在权限数据中存在,如果不存在就不显示标签包含内容,如果存在则显示。
在这里只要遇到注解或shiro jsp标签授权,就会调用realm查询数据库,在这里需要引入缓存解决。
shiro缓存
针对授权时频繁查询数据库的问题,引入shiro缓存。
缓存流程
用户认证通过。
用户第一次授权:调用realm查询数据库。
用户第二次授权:不调用realm查询数据库,直接从缓存中读取授权信息。
使用 ehcache
添加Ehcache的jar包
分支主题
配置Ehcache配置文件
配置cacheManager
清空缓存
当用户权限修改后,用户再次登录shiro会自动调用realm从数据库获取权限数据,如果在修改权限后想立即清除缓存则可以调用realm的clearCache方法清除。
在CustomRealm 中定义clearCached方法:
sessionManager使用
验证码功能实现
实现方式
shiro使用FormAuthenticationFilter进行表单认证,验证码校验的功能应该加在FormAuthenticationFilter中,在认证之前进行验证码校验。
自定义FormAuthenticationFilter
配置自定义的FormAuthenticationFilter
在spring-shiro.xml文件中配置
修改 shiroFilter 配置
修改 LoginController 的 login 方法
在登录页面添加验证码
记住我功能实现
用户登录选择”记住我”选项,本次登录成功会向cookie写身份信息,下次登录从cookie中取出身份信息实现自动登录。
用户身份信息相关类实现 java.io.Serializable 接口
配置 rememberMeManager
添加到securityManager中
修改登录页面
修改rememberMe的input名称
使用UserFilter
0 条评论
下一页