Java基础、中级、高级、架构面试资料

安全开源权限框架Shiro架构设计原理解析

JAVA herman 7460浏览 0评论
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog2,发送下载链接帮助你免费下载!
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云

Shiro并不是一个新技术型框架,它的使用场景非常广泛!主要对我们应用中的权限模块进行统一的设计,简化我们的逻辑和设计,让我们能更好的关注业务本身。

常见权限漏洞

前面我写过两篇常见的权限漏洞:水平权限漏洞垂直权限漏洞。权限设计在应用中非常常见,像淘宝之类的电商网站的权限也非常复杂。一个项目要有好的权限管理,需要非常细致的设计和开发,而大多数的开发者都没有太多的时间和精力来关注权限模块,因此Shiro就可以更好的解决我们的问题和需求。

权限框架

在Shiro之前,权限框架有JAAS和Spring Security,但是它们在Shiro面前都不够强大和灵活。Shiro的前身是J-security,后来更名为Shiro。
JAAS面世的时间最早,但是鉴于其在使用上有很大的限制,很少有人真正的使用它。可以说它不是一个好的应用程序级别的安全框架。
Spring Security目前是Java安全框架领域当之无愧的老大,已经非常成熟了;如果使用Spring框架,可以首选Spring Security,但是对于单应用来说,Shiro更显简单方便。

Shiro的优点

Shiro是一个强大而灵活的开源安全框架,能够非常清晰的处理认证、授权、管理会话以及密码加密。它的优点如下:
易于理解的 Java Security API;
简单的身份认证(登录),支持多种数据源(LDAP,JDBC,Kerberos,ActiveDirectory 等);
对角色的简单的签权(访问控制),支持细粒度的签权;
支持一级缓存,以提升应用程序的性能;
内置的基于 POJO 企业会话管理,适用于 Web 以及非 Web 的环境;
异构客户端会话访问;
非常简单的加密 API;
不跟任何的框架或者容器捆绑,可以独立运行。

Shiro整体架构

Shiro的认证和签权可以通过JDBC、LDAP或者Active Directory来访问数据库、目录服务器或者Active Directory中的人员以及认证/签权信息。SessionManager通过会话DAO可以将会话保存在cache中,或者固化到数据库或文件系统中。下图为Shiro的整体架构图:
Shiro设计架构
从上图可以看出,Shiro主要有四个组件:
SecurityManager
典型的Facade,Shiro通过它对外提供安全管理的各种服务。
Authenticator
对“Who are you ?”进行核实。通常涉及用户名和密码。
这个组件负责收集principals和credentials,并将它们提交给应用系统。如果提交的credentials跟应用系统中提供的credentials吻合,就能够继续访问,否则需要重新提交principals和credentials,或者直接终止访问。
Authorizer
身份份验证通过后,由这个组件对登录人员进行访问控制的筛查,比如“who can do what”, 或者“who can do which actions”。Shiro采用“基于Realm”的方法,即用户(又称 Subject)、用户组、角色和permission的聚合体。
Session Manager
这个组件保证了异构客户端的访问,配置简单。它是基于POJO/J2SE的,不跟任何的客户端或者协议绑定

安全模型

看了Shiro的框架图,相信大家已经能够体会到这个工具的简单了。下面在看看Shiro权限管理的安全模型:
Shiro权限管理
从上图中可以看出,Shiro安全模型主要分为5个部分:
Subject是安全领域术语,除了代表人,它还可以是应用。在单应用中,可将其视为User的同义词。
Principal是Subject的标识,一般情况下是唯一标识,比如用户名。
Role和Permission分别代表了不同粒度的权限,从上图中可以看出 Role的粒度更大些,Permission代表了系统的原子权限,比如数据的修改、删除权限。对于简单的权限应用,可以不需要Permission。
Realm是一个执行者,负责真正的认证和鉴权。

Shiro框架的核心组件

下图为Shiro框架的核心类:
Shiro的组件
AuthenticationToken和AuthenticationInfo
前者在认证前使用,描述认证所需的信息,最常用的就是 username和password对;后者在认证后使用,内容同前,但是表示已经经过认证的信息。
RememberMe
代表的是一种可能状态,并不表示该 Subject 已经经过了认证。对于一些普通的操作,这种可能状态并无大碍,但一旦涉及安全敏感的操作,必须经过认证。
Credentials和redentialsMatcher
Credentials是Subject的证书,在认证时使用,最常用的就是password。在通常情况下,为了安全起见,Subject的credentials都需要加密保存,于是CredentialsMatcher的作用就体现出来了。CredentialsMatcher 需要将加密后的证书跟用户登录时提供的证书进行比对,完成认证的过程。
PAM= Pluggable Authentication Modules
在有多个Realm的时候使用。由认证策略决定认证结果,即PAM=Relams + 认证策略。一般的策略有3种:AllSuccessful、AtLeastOneSuccessful和FirstSuccessful。
AuthorizationInfo
可以看成是Role + Permission的组合体。

PermissionResolver和Permission
在Shiro中,权限被转化为一种字符串描述(字符串分级表示,称之为WildcardPermission),从而将权限转化为类似于对象equals的操作(Shiro中的implies方法)。
内置的权限有2个:
AllPermission,总是返回true
WildcardPermission,权限字符串的表示方式。
这里重点声明一下。WildcardPermission是Shiro的精妙之处,我们可以将权限表示成字符串,这样对权限的控制可以不拘泥于物理存储,比如对messagge类具有修改和删除权限可以标识为:message:update,delete:*,其中‘ * ’表示所有;第一级分隔符为‘ : ’;第二级分隔符为‘ , ’,而对于权限字符串的解释完全可以由应用自己来定。
如果要比较权限字符串,可以使用permission1.implies(permission2),它分别比较对应位置的字符串,在如下情况中,结果会返回true:
permission1中的子串有 * 或 permission1 子串 ==permission2 子串;
permission1无子串,permission2 有;
permission1有子串,permission2 无,permission1 的所有子串都是 *。
总的说来,Shiro 中的 Permission 需要注意如下内容:
权限的比较实际是字符串的比较,只不过是考虑到了字符串的分级
字符串的分级划分完全由使用者自己决定,Shiro的惯例是3级:资源 : 操作 : 实例。
字符串的使用必须一致,分隔符之间不要有空格,避免无意间引入的不一致。如:定义使用“file : create, update : 1”,而验证使用“file : update”,那么分解之后一个是“ update ”,一个是“ update”,因空格而引起不等

Realm
这是一个实际访问安全实体的组件,一般是应用相关的,跟数据源的关系是 1-1。它负责完成认证和鉴权,getAuthenticationInfo代表了login的尝试,鉴权方法则由Authorizer继承而来。此处也体现了Shiro代码的另一个特点,通过继承来扩充功能。
Session
它关联一个Subject的上下文,其作用类似于在HttpSession中保存用户标识,session一旦过期,则重新登录。Shiro的Session是独立的,其目的是做到环境无关性。为了利用Web环境中,Shiro实现了一个直接使用HttpSession的WebSession。
SecurityManager
这是一个Façade 接口,=Authenticator + Authorizer + SessionFactory。在整体框架图中已经看到了它在Shiro中所处的位置。其特点同Realm,一样是使用继承不断地扩充功能。对于Web应用一般使用DefaultWebSecurityManager。
Filter
在Web环境下使用filter进行认证和权限检查是毋庸置疑的,而Shiro的特点则在于由一个主Filter将一群子filter串起来。
在实际使用时,须注意:
web.xml中只需配置JSecurityFilter。对于Spring应用,则使用SpringJSecurityFilter;
子filter作为主filter的配置参数值出现,特点是:顺序相关
对于多个URL,验证顺序是由上至下,类似Exception的匹配。因此,使用顺序应该是由细到粗。
对于同一URL,子filter 的验证顺序是从左至右的AND操作。
如果配置值中含有分隔符,如Permission,就需要使用引号来转义。
Subject
subject代表了一个用户的状态和操作,它提供了所有安全相关的操作,包括认证和签权。可以将其视为另一种形式的Façade。缺省实现是将这些操作委派给其内部包含的SecurityManager。
Configuration
configuration负责将所有这些组件串起来,最终创建SecurityManager。在 Shiro中,缺省格式是ini。
JSecurityFilter创建Configuration 实例,并将ini参数值传给Configuation。在Spring环境中,分别使用SpringJSecurityFilter和SpringIniWebConfiguration。
Configuration实际就是SecurityManager的Factroy,对SpringIniWebConfiguration而言,它需要知道SecurityManager的BeanName,该值由SpringJSecurityFilter的初始化参数“securityManagerBeanName”值决定。即SpringJSecurityFilter,实际有两个初始化参数:
config,是ini配置文件内容
securityManagerBeanName,是SecurityManager的BeanName

SecurityUtils

这是Shiro 中最重要的工具类,由它可以方便地获得Subject和SecurityManager。

Shiro的其他支持特性

AOP提供AOP方面的支持,实现对某个类某个方法的拦截,从而使权限控制延伸至类的方法。
Cache提供缓存支持
Codec提供编码方面的支持
Crypto提供加密支持
IO从多个资源位置读写原始数据
JNDI提供jndi支持
util工具类支持
标签类用于Web页面

版权声明:本文为博主原创文章,未经博主允许不得转载。

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!

本文原文出处:业余草: » 安全开源权限框架Shiro架构设计原理解析