SHiro学习笔记

来源:互联网 发布:triz 矛盾矩阵 编辑:程序博客网 时间:2024/05/17 06:42

简介

Shiro 是一个强大而灵活的开源安全框架,能够非常清晰的处理认证、授权、管理会话以及密码加密。如下是它所具有的特点:

1.   易于理解的 Java Security API;

2.   简单的身份认证(登录),支持多种数据源(LDAP,JDBC,Kerberos,ActiveDirectory等);

3.   对角色的简单的签权(访问控制),支持细粒度的签权;

4.   支持一级缓存,以提升应用程序的性能;

5.   内置的基于 POJO 企业会话管理,适用于 Web 以及非 Web 的环境;

6.   异构客户端会话访问; SecurityManager每个用户会话时效性的状态。

7.   非常简单的加密 API;Cryptography 密码加密 - 保护或隐藏数据防止被偷窥;

8.   不跟任何的框架或者容器捆绑,可以独立运行。

整体架构:

从上图可以看出,Shiro 主要有四个组件:

SecurityManager

安全管理器,是Apache Shiro框架的核心,它是典型的Facade模式,Shiro框架通过它来管理所有的安全服务。Subject代表了当前用户的安全操作,而SecurityManager管理了所有用户的安全操作。如何建立SecurityManager呢?这取决于你的应用程序环境,若是web应用程序,通常在web.xml指定Shiro web servlet过滤器;若是独立的应用程序,你需要其他配置方式。在每个应用程序中几乎只有一个SecurityManager实例,它本质上是一个应用程序单例。在Shiro几乎所有的东西,默认SercurtyManager实现POJOs和一些POJO兼容的配置 -normal Java code,spring XML,YAML,.properties和.ini文件等等。因此,Shiro通过基于文本的INI配置一个默认的“共同点”的解决方案。

Authenticator

对“Who are you ?”进行核实。通常涉及用户名和密码。

它分为三个步骤,如下:

1.     收集用户身份信息,也称为principals(主体),并提供身份证明,也称为credentials(凭证)。

AuthenticationToken token = new UsernamePasswordToken(username, password);

2.     提交主体和凭证到系统。

Subject currentUser = SecurityUtils.getSubject();  

currentUser.login(token); 

3.     如果提供的凭证匹配系统期望的用户身份,则用户身份验证通过,否则反之。

Shiro的登录方法被调用时,SecurityManager将接收AuthenticationToken,并将其分派到一个或多个配置的Realm,允许每个Realm按要求执行认证检查。若登录失败,则抛出AuthenticationException异常。当然你也可以抛出AuthenticationException异常的子类,不过,一般应用程序建议抛出AuthenticationException异常,提示用户账号/密码错误,防止被攻击。当然,具体应用程序具体分析。

Authorizer

身份份验证通过后,由这个组件对登录人员进行访问控制的筛查,比如“who can do what”, 或者“whocan do which actions”。Shiro 采用“基于Realm”的方法,即用户(又称 Subject)、用户组、角色和 permission 的聚合体。代码示例:

if ( subject.isPermitted(“user:create”) ) { 

SessionManager

Apache Shiro提供了一个独特的安全框架:可在任何应用程序或架构层一致的使用Session API。意味着Shiro为任何的应用程序提供了会话编程模式 - 从小型的后台独立应用程序到大型的集群Web应用程序。Shiro会话的重要好处如下:

  • 它独立于容器之外,例如:会话集群(EnterpriseCacheSessionDAO),有很多容器在容错和故障转移都有自己特殊的方式,Tomcat与jetty不同,也与Websphere不同,等等。但是使用Shiro会话,你就拥有独立于容器的集群解决方案。Shiro架构支持可插拔的会话数据存储,例如企业缓存(EHCache)、关系型数据库和NoSQL等等。这就意味着只要你一旦配置会话集群,它就会同样的方式工作,跟部署的环境无关 - Tomcat、Jetty、JEE服务器和单独的应用程序等等。
  • 跨客户端技术共享会话数据。例如:如果用户同时使用Swing桌面客户端和Web应用程序时,它们可以共享会话数据。

Session DAO

会话数据访问对象,用于会话的CRUD,比如我们想把Session保存到数据库,那么可以实现自己的SessionDAO,通过如JDBC写到数据库;比如想把Session放到Memcached中,可以实现自己的Memcached SessionDAO;另外SessionDAO中可以使用Cache进行缓存,以提高性能。

CacheManager

缓存控制器,来管理如用户、角色、权限等的缓存的;因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能。

Shiro’scache support is basically an abstraction (wrapper) API that will ‘sit’ on topof an underlying production Cache mechanism

CacheManager returns Cache instances and various Shiro components usethose Cache instances to cache data as necessary. Any Shiro

componentthat implements CacheManagerAware will automatically receive a configured CacheManager, whereit can be used to acquire Cache instances.

Cryptography

加密模块。加密就是隐藏或混淆数据以防止被窥视的过程。加密可以用在Shiro任何的地方。Shiro加密是为了简化jdk加密的。Shiro关注的两个领域是加密哈希(信息摘要)和加密密码。

MD5String hex = new Md5Hash(myFile).toHex(); 

SHA-512和密码的Base64编码new Sha512Hash(password, salt, count).toBase64();

可逆加密:AesCipherService cipherService = new AesCipherService();

安全模型

从 Shiro 的框架图,已经能够体会到这个工具的简单了。下面让我们来看看 Shiro 是如何工作的。先了解一下它的安全模型吧!见下图:

图 2. 安全模型

上图中,涉及了 Shiro 的五个概念:

Subject: 是安全领域术语,除了代表人,它还可以是应用。在单应用中,可将其视为 User 的同义词。

Principal 是 Subject 的标识,一般情况下是唯一标识,比如用户名。

Role 和 Permission 分别代表了不同粒度的权限,从上图中可以看出 Role 的粒度更大些,Permission 代表了系统的原子权限,比如数据的修改、删除权限。对于简单的权限应用,可以不需要 Permission。

Realm 是一个执行者,负责真正的认证和鉴权。

实现应用的安全模块的关键在于:定义合适的 role 和permission,这就需要遵循如下原则:

role 没有实质内容,只是代表一组 permission,目的是为了管理的方便,一般都是动态定义;

permission 一般都是预先定义好的,不允许动态改变,除非源代码改动,它才会变化,它是整个安全模块的基础;

要使 permission 也能动态定义,并非不可能,但是这将使鉴权非常复杂,甚至可能导致鉴权语句遍布整个程序,得不偿失;

当然有一个例外:如果知道 permission 动态定义的规则和鉴权规则,如 Grails 的 fileter 中“${controllerName}:${actionName}:${params.id}”也可实现permission 的动态定义

常见类:

AuthenticationToken和 AuthenticationInfo

前者在认证前使用,描述认证所需的信息,最常用的就是 username 和password 对;后者在认证后使用,内容同前,但是表示已经经过认证的信息。

RememberMe

代表的是一种可能状态,并不表示该 Subject 已经经过了认证。对于一些普通的操作,这种可能状态并无大碍,但一旦涉及安全敏感的操作,必须经过认证。

Credentials 和CredentialsMatcher

Credentials 是 Subject 的证书,在认证时使用,最常用的就是 password。在通常情况下,为了安全起见,Subject 的credentials 都需要加密保存,于是 CredentialsMatcher 的作用就体现出来了,见下图:

图 4. CredentialsMatcher 的作用

这里 CredentialsMatcher 需要将加密后的证书跟用户登录时提供的证书进行比对,完成认证的过程。

PAM=Pluggable Authentication Modules

在有多个 Realm 的时候使用。由认证策略决定认证结果,即 PAM= Relams + 认证策略。一般的策略有 3 种:AllSuccessful、AtLeastOneSuccessful和 FirstSuccessful。

AuthorizationInfo

可以看成是 Role + Permission 的组合体。

PermissionResolver和 Permission

它们之间的关系如下:

图 5. 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 代码的另一个特点,通过继承来扩充功能。以常用的 JdbcRealm 为例,其继承链如下:

图 6. JdbcRealm 的继承链

Shiro提供了开箱即用的Realms去连接许多安全的数据源(目录),例如:LDAP、关系型数据库(JDBC)和文本配置源(.ini.properties文件等)等等。如果默认的Realms不能满足你的需求时,你可以插入你自己的Rleam来实现自定义数据源。

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 串起来:

如果配置值中含有分隔符,如 Permission,就需要使用引号来转义。

Subject

当前执行用户,这个用户不一定是人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着与当前应用交互的任何东西,当然,我们一般把它当做用户来看。

一旦你获取了主体,你可以在Shiro中对当前用户进行大部分的安全操作,例如登录、注销、访问会话、执行授权检查等等。你可以在代码的任何地方很方便的访问主体,在有需要的地方进行安全操作。

Configuration

configuration 负责将所有这些组件串起来,最终创建 SecurityManager。在Shiro 中,缺省格式是 ini。整个配置关系如下图:

图 8. 配置关系

其中:

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。

杂项

AOP,提供 AOP 方面的支持,实现对某个类某个方法的拦截,从而使权限控制延伸至类的方法。

Cache,提供缓存支持

Codec,提供编码方面的支持

Crypto,提供加密支持

IO,从多个资源位置读写原始数据

JNDI,提供 jndi 支持

util,工具类支持

标签类,用于 Web 页面

Web支持

1.     web.xml定义Shiro Servlet过滤器。

2.     配置 url的权限,如anonuserpermsauthc等等是Shiro内置的安全相关的特殊过滤器,Shiro提供开箱即用。

/assets/** =anon

/user/signup =anon

/user/** = user

/rpc/rest/** =perms[rpc:invoke], authc

/** = authc

3.     标签库

<shiro:user>

    <!-- shiro:principal打印Subject的主体 - 在示例中,就是用户名 -->

    <shiro:principal/>!

</shiro:user>

<shiro:guest>

    <!-- 没有登陆 - 就是guest,显示注册链接  -->

    ! <a href=”register.jsp”>Registertoday!</a>

</shiro:guest>

测试

单元测试: extendsAbstractShiroTest,并mock Subject的实现

集成测试:You can easily perform integration testing inShiro as well. Shiro’s SecurityManager instance and things it wraps (like Realms andSessionManager, etc) are all very lightweight POJOs that use very littlememory. This means you can create and tear down a SecurityManager instance for every test class you execute. Whenyour integration tests run, they will be using ‘real’ SecurityManager and Subject instances like your application will be usingat runtime.

参考文章:

简介: http://blog.csdn.net/u012102401/article/details/50053547

简单实例:http://blog.csdn.net/u012102401/article/details/50069775

ibm实例(spring集成、验证码和单点登录):https://www.ibm.com/developerworks/cn/java/j-lo-shiro/

https://www.ibm.com/developerworks/cn/opensource/os-cn-shiro/

官网:http://shiro.apache.org/documentation.html

权限语法:http://shiro.apache.org/permissions.html

原创粉丝点击