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

  1. 易于理解的 Java Security API;
  2. 简单的身份认证(登录),支持多种数据源(LDAP,JDBC,Kerberos,ActiveDirectory 等);
  3. 对角色的简单的签权(访问控制),支持细粒度的签权;
  4. 支持一级缓存,以提升应用程序的性能;
  5. 内置的基于 POJO 企业会话管理,适用于 Web 以及非 Web 的环境;
  6. 异构客户端会话访问;
  7. 非常简单的加密 API;
  8. 不跟任何的框架或者容器捆绑,可以独立运行。

首先,我们来看看的 Shiro 的整体架构,见下图:

图 1. 整体架构

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

  1. SecurityManager

    典型的 Facade,Shiro 通过它对外提供安全管理的各种服务。

  2. Authenticator

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

    这个组件负责收集 principals 和 credentials,并将它们提交给应用系统。如果提交的 credentials
    跟应用系统中提供的 credentials 吻合,就能够继续访问,否则需要重新提交 principals 和
    credentials,或者直接终止访问。

  3. Authorizer

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

  4. Session Manager

    这个组件保证了异构客户端的访问,配置简单。它是基于 POJO/J2SE 的,不跟任何的客户端或者协议绑定。

图 2. 安全模型

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

  • Subject 是安全领域术语,除了代表人,它还可以是应用。在单应用中,可将其视为 User 的同义词。
  • Principal 是 Subject 的标识,一般情况下是唯一标识,比如用户名。
  • Role 和 Permission 分别代表了不同粒度的权限,从上图中可以看出 Role 的粒度更大些,Permission 代表了系统的原子权限,比如数据的修改、删除权限。对于简单的权限应用,可以不需要 Permission。
  • Realm 是一个执行者,负责真正的认证和鉴权。

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

  1. role 没有实质内容,只是代表一组 permission,目的是为了管理的方便,一般都是动态定义;
  2. permission 一般都是预先定义好的,不允许动态改变,除非源代码改动,它才会变化,它是整个安全模块的基础;
  3. 要使 permission 也能动态定义,并非不可能,但是这将使鉴权非常复杂,甚至可能导致鉴权语句遍布整个程序,得不偿失;
  4. 当然有一个例外:如果知道 permission 动态定义的规则和鉴权规则,如 Grails 的 fileter 中“${controllerName}:${actionName}:${params.id}”也可实现 permission 的动态定义

图 3. 关键类

AuthenticationToken 和 AuthenticationInfo

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

RememberMe

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

Credentials 和 CredentialsMatcher

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 需要注意如下内容:

  1. 权限的比较实际是字符串的比较,只不过是考虑到了字符串的分级
  2. 字符串的分级划分完全由使用者自己决定,Shiro 的惯例是 3 级:资源 : 操作 : 实例。
  3. 字符串的使用必须一致,分隔符之间不要有空格,避免无意间引入的不一致。如:定义使用“file : create, update :
    1”,而验证使用“file : update”,那么分解之后一个是“ update ”,一个是“ update”,因空格而引起不等。

Realm

这是一个实际访问安全实体的组件,一般是应用相关的,跟数据源的关系是
1-1。它负责完成认证和鉴权,getAuthenticationInfo 代表了 login 的尝试,鉴权方法则由 Authorizer
继承而来。此处也体现了 Shiro 代码的另一个特点,通过继承来扩充功能。以常用的 JdbcRealm 为例,其继承链如下:

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

在实际使用时,须注意:

  1. web.xml 中只需配置 org.apache.shiro.web.servlet.ShiroFilter和EnvironmentLoaderListener。对于 Spring 应用,则使用 DelegatingFilterProxy;
  2. 子 filter 作为主 filter 的配置参数值出现,特点是:顺序相关
    1. 对于多个 URL,验证顺序是由上至下,类似 Exception 的匹配。因此,使用顺序应该是由细到粗。
    2. 对于同一 URL,子 filter 的验证顺序是从左至右的 AND 操作。
  3. 如果配置值中含有分隔符,如 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。

杂项

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

常用标签:

    • principal, 输出当前用户的标识
    • hasRole,判断当前用户是否属于给定的角色,参数:name
    • hasPermission, 判断当前用户是否具有指定的权限,参数:type,action 或者 permission
    • isLoggedIn, 判断当前用户是否已经登录
    • hasAnyRole,判断当前用户是否属于给定的某个角色,参数:in

shior笔记的更多相关文章

  1. Shiro学习笔记总结,附加" 身份认证 "源码案例(一)

    Shiro学习笔记总结 内容介绍: 一.Shiro介绍 二.subject认证主体 三.身份认证流程 四.Realm & JDBC reaml介绍 五.Shiro.ini配置介绍 六.源码案例 ...

  2. git-简单流程(学习笔记)

    这是阅读廖雪峰的官方网站的笔记,用于自己以后回看 1.进入项目文件夹 初始化一个Git仓库,使用git init命令. 添加文件到Git仓库,分两步: 第一步,使用命令git add <file ...

  3. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  4. SQL Server技术内幕笔记合集

    SQL Server技术内幕笔记合集 发这一篇文章主要是方便大家找到我的笔记入口,方便大家o(∩_∩)o Microsoft SQL Server 6.5 技术内幕 笔记http://www.cnbl ...

  5. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  6. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  7. NET Core-学习笔记(三)

    这里将要和大家分享的是学习总结第三篇:首先感慨一下这周跟随netcore官网学习是遇到的一些问题: a.官网的英文版教程使用的部分nuget包和我当时安装的最新包版本不一致,所以没法按照教材上给出的列 ...

  8. springMVC学习笔记--知识点总结1

    以下是学习springmvc框架时的笔记整理: 结果跳转方式 1.设置ModelAndView,根据view的名称,和视图渲染器跳转到指定的页面. 比如jsp的视图渲染器是如下配置的: <!-- ...

  9. 读书笔记汇总 - SQL必知必会(第4版)

    本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...

随机推荐

  1. Java中File类总结

    /** * @Title:JavaFile.java * @Package:com.yhd.chart.model * @Description:File类测试 * @author:Youhaidon ...

  2. php simpleXML操作xml的用法

    XML简介 XML是一种流行的半结构化文件格式,以一种类似数据库的格式存储数据.在实际应用中,一些简单的.安全性较低的数据往往使用 XML文件的格式进行存储.这样做的好处一方面可以通过减少与数据库的交 ...

  3. 【linux】安装mysql出现 no curses错误解决方法

    安装mysql,在./configure时出现错误:error: No curses/termcap library found的解决办法 mysql版本:5.1.30 已经不记得这次是第几次安装my ...

  4. VxWorks程序指南

    ******************************************* 一.任务 ******************************************* 任务状态:挂起 ...

  5. 【mongodb系统学习之八】mongodb shell常用操作

    八.mongodb  shell常用基础操作(每个语句后可以加分号,也可以不加,看情况定(有的工具中可以不加),最好是加): 1).进入shell操作界面:mongo,上边已有演示: 2).查看当前使 ...

  6. JavaScript去除日期中的“-”

    JavaScript去除日期中的"-" 1.说明 经常会出现这样的情况,页面的日期格式是:YYYY-MM-DD,而数据库中的日期格式是:YYYYMMDD,两者之间需要转换一下,方能 ...

  7. JavaScript控制输入框只能输入非负正整数

    1.问题背景 问题:一个输入框,输入的是月份,保证输入的内容只能是非负正整数 2.JavaScript代码 function checkMonth() { $("month").k ...

  8. C# 扩展方法 白话总结

    我们在变成的时候时常遇到这样的问题,new了一个系统内的对象之后,我们想要对该对象有一个方法可是却点不出来,说明该对象本身没有声明该方法,可是微软又不允许我们去该对象的代码,怎么办? 在C# 3.0  ...

  9. 使input文本框不可编辑的3种方法

    一:disabled disabled 属性规定应该禁用 input 元素,被禁用的 input 元素,不可编辑,不可复制,不可选择,不能接收焦点,后台也不会接收到传值.设置后文字的颜色会变成灰色.d ...

  10. 【原】spring boot添加cros全局过滤器

    新增一个过滤器类并实现filter接口 public class CorsFilter implements Filter { final static org.slf4j.Logger logger ...