Apache shiro 安全框架入门学习

目录

前言

一、什么是Apache Shiro?

二、核心概念介绍及架构

1.整体框架图

2.核心概念

3.整体功能

三、功能详解

总结



前言

此文章为自己学习Shiro框架做学习笔记之用,从shiro涉及到的几个概念的讲解,到简单的单元测试,最后实现权限框架的搭建及测试


 

一、什么是Apache Shiro?

Apache Shiro 是ASF旗下的一款开源软件,它是一个功能强大且易于使用的Java安全框架。Shiro将目标集中于Shiro开发团队所称的“四大安全基石”-认证(Authentication)、授权(Authorization)、会话管理(Session Management)和加密(Cryptography)

 

二、核心概念介绍及架构

1.整体框架图

                                  Apache shiro 安全框架入门学习

 

2.核心概念

1、subject(主题):代表了正在操作的当前“用户”,这个用户并不一定是人也也可以指第三方系统或任何类似的东西。一旦您获得了主题,您就可以立即访问当前用户使用Shiro想要做的90%的事情,比如登录、注销、访问他们的会话、执行授权检查等。

2、securityManager(安全管理器):它是shiro的核心,所有与安全有关的操作都会与securityManager进行交互,他管理shiro架构图中的所有模块,包括缓存管理,会话管理 ,Realm等等。

3、realm(数据域):可以看作是JDBC,充当Shiro和应用程序安全数据之间的“桥梁”,当实际需要与安全相关的数据(如用户帐户)进行交互以执行身份验证(登录)和授权(访问控制)时,Shiro会从一个或多个为应用程序配置的领域中查找这些内容。realm可以有多个,但是至少得有一个。Shiro提供了开箱即用的realm,可以连接到许多安全数据源,如LDAP、关系数据库(JDBC)、文本配置源(如INI)和属性文件,等等。如果默认的realm(固定数据库表结构)不满足您的需求,可以添加您自己的领域实现来表示自定义数据源。

4、Authenticator(登录认证器):负责主体登录认证的,如果用户觉得 Shiro 默认的 不好,可以自定义实现;其需要认证策略(Authentication Strategy),即什么情况下算用户认证通过了

5、Authrizer(访问控制器):用来决定主题是否有权限进行相应的操作,即控制什么角色的主题或什么权限的主题能进行当前操作

6、SessionManager(会话管理器):Session 需要有人去管理 它的生命周期,这个组件就是 SessionManager;而 Shiro 并不仅仅可以用在 Web 环境,也 可以用在如普通的 JavaSE 环境、EJB 等环境;所有呢,Shiro 就抽象了一个自己的 Session 来管理主体与应用之间交互的数据;这样的话,比如我们在 Web 环境用,刚开始是一台 Web 服务器;接着又上了台 EJB 服务器;这时想把两台服务器的会话数据放到一个地方, 这个时候就可以实现自己的分布式会话(如把数据放到 Rediscached 服务器)

7、SessionDAO(会话持久):DAO 大家都用过,数据访问对象,用于会话的CRUD,比如我们想把 Session 保存到数据库,那么可以实现自己的 SessionDAO,通过JDBC 写到数据库;还可以把 Session 放到缓存 中,可以在SessionDao中设置RedisCacheManager缓存管理器 ,当服务重启的时候,当前登录的用户就不用因为session丢失而重新登录

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

9、Cryptography:密码模块,Shiro 提高了一些常见的加密组件用于如密码加密/解密的

 

3.整体功能

1、Authentication:身份认证

2、Authorization:权限校验

3、AuthorizationFilter:过滤器

4、SessionManager:会话管理,用户从登录到退出是一次会话,所有的信息都保存在会话中。普通的java se环境中也支持

5、cryptography:数据加密,如对用户密码进行加密,避免将密码明文存入数据库中。

6、Web support:非常容易集成到web环境中。

7、Caching:缓存,将用户信息和角色权限等缓存起来,不必每次去查

8、Concurrency:支持多线程,在一个线程中开启新的线程,能把权限传过去。

9、Testing:提供测试功能

10、Run As:允许一个用户假装为另一个用户的身份进行访问。

11、Remember me: 记住用户,一次登录后下次不用登录。

 

三、功能详解

1、Authentication:身份认证(登录)

      使用principals(身份,也就是账号)和credentials(证明,密码或者证书)来对用户进行认证。

①.身份认证的流程图

                                       Apache shiro 安全框架入门学习

②.身份认证的具体流程

  1. 首先用户在Controller层中获取用户输入的账号及密码,根据账号信息,初始化一个UsernamePasswordToken
  2. 调用 Subject.login(token)进行登录,其会自动委托给 SecurityManager  
  3.  SecurityManager 负责真正的身份验证逻辑;它会委托给他所管理的 Authenticator 进行身份验证;  
  4.  Authenticator 才是真正的身份验证者,Shiro API 中核心的身份认证入口点,开发者可以自定义插入自己的实现; 
  5.  Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证,默认ModularRealmAuthenticator 会调用 AuthenticationStrategy 进行多 Realm 身份验证;
  6.  Authenticator 会把相应的 token 传入 Realm,这里的Realm一般都是根据自己的业务需求自定义的Realm,Realm从数据库或ini文件中获取用户的真实credentials(密码),此处可以配置多个 Realm,将按照相应的顺序及策略进行访问。Realm再根据其中的CredentialsMatcher进行密码校验
  7.  CredentialsMatcher是realm中的密码校验器,默认类型SimpleCredentialsMatcher只比较realm中token的密码和数据库查找出来的密码文本内容是否一致,而现实业务中的密码不可能明文存储,一般都是加密过后的,需要自定义CredentialsMatcher,比如HashedCredentialsMatcher,如果密码匹配通过则返回True,否则抛出异常。开发需要在subject.login外层加try-catch捕获这些异常,从而来判断是否登录成功,是否密码错误或用户不存在等各种情况

2、权限校验

  ①.授权相关的几个关键对象:

  1. 主体(Subject):在 Shiro 中使用 Subject 代表该用户。用户只有授权后才允许访 问相应的资源
  2. 资源(Resource):系统中所有可以访问的东西,如页面、按钮、链接、数据等
  3. 权限(Permission):安全策略中的原子授权单位,通过权限我们可以表示在应用中用户有没有操作某个资源的 权力。即权限表示在应用中用户能不能访问某个资源
  4. 角色(Role):可以理解为权限集合,一般情况下我们会赋予用户角色而不是权 限,即这样用户可以拥有一组权限,赋予权限时比较方便

   ②.授权流程图

             Apache shiro 安全框架入门学习

 ③.授权流程详细

  1. 首先调用 Subject.isPermitted*/hasRole*接口,其会委托给 SecurityManager,而 SecurityManager 接着会委托给 Authorizer
  2. Authorizer 是真正的授权者,如果我们调用如 isPermitted(“user:view”),其首先会通过 PermissionResolver 把字符串转换成相应的 Permission 实例
  3. 在进行授权之前,其会调用相应的 Realm 获取 Subject 相应的角色/权限用于匹配传入的 角色/权限
  4. Authorizer 会判断 Realm 的角色/权限是否和传入的匹配,如果有多个 Realm,会委托给 ModularRealmAuthorizer 进行循环判断,如果匹配如 isPermitted*/hasRole*会返回 true,否则返回 false 表示授权失败

 ④.ModularRealmAuthorizer 进行多 Realm 匹配流程:

  1. 首先检查相应的 Realm 是否实现了实现了 Authorizer;
  2. 如果实现了 Authorizer,那么接着调用其相应的 isPermitted*/hasRole*接口进行匹配;
  3. 如果有一个 Realm 匹配那么将返回 true,否则返回 false;

    

 ⑤.如果 Realm 进行授权的话,应该继承 AuthorizingRealm,其流程是:

  1. 如果调用 hasRole(),则直接获取 AuthorizationInfo.getRoles()与传入的角色比较即可;
  2. 首先如果调用如 isPermitted(“user:view”),首先通过 PermissionResolver 将权限字符串 转换成相应的 Permission 实例,默认使用 WildcardPermissionResolver,即转换为通配符的 WildcardPermission
  3. 通 过 AuthorizationInfo.getObjectPermissions() 得 到 Permission 实 例 集 合 ;通过 AuthorizationInfo. getStringPermissions()得到字符串集合并通过 PermissionResolver 解析为 Permission 实例;然后获取用户的角色,并通过 RolePermissionResolver 解析角色对应的权 限集合(默认没有实现,可以自己提供);通过上面的三种情况获取了所有的权限集合。
  4. 接着调用 Permission. implies(Permission p)逐个与传入的权限比较,如果有匹配的则返回 true,否则 false;

总结

 

 

相关文章: