Shiro能帮助我们干什么?
Apache Shiro 是Java领域内的一款简单易用而又强大的一款安全框架,主要用于登录验证、授权、加密、会话管理。Shiro拥有简单应用的API,您可以快送的使用它来保护您的应用,不管是小到手机应用还是到大的Web企业级应用。
从上面的一段话我们可以提取到以下信息:
- Shiro简单易用而又强大
- 主要应用于登录验证、授权、加密、会话管理。
第一点需要在中使用中慢慢体会,第二点是我们主要关注的,这里我们一点一点的讲。
这里我们回忆一下HTTP协议和Servlet, 早期的HTTP协议是无状态的, 这个无状态我们可以这么理解,你一分钟前访问和现在访问一个网站,服务端并不认识你是谁,但是对于Web服务端开发者来说, 这便无法实现访问控制,某些信息只能登录用户才能看,各自看各自的。这着实的有点限制住了Web的发展,为了让HTTP协议有状态,RFC-6235提案被获得批准,这个提案引入了Cookie, 是服务器发送到用户浏览器并保存在本地的一小块数据,它会再浏览器下次向同一服务器再发起请求时被携带并发送到服务器上,服务端就可以实现“识别”用户了。
在原生的Servlet场景中如下:
* 不重写init方法,过滤器无法起作用 // 这里采取了暂时写死,目前只放行登录请求的URL // 放行,此请求进入下一个过滤器 * 由登录过滤器来执行登录验证操作 * 要求用户名和密码不为空的情况下才进行下一步操纵 // 这里假装去数据库去查账号和密码 // 放到下一个过滤器,如果这是最后一个过滤器,那么这个请求会被放行到对应的Servlet中前面提到, 为了实现让HTTP协议有“状态”, 浏览器引入了Cookie, 存放服务端发送给客户端的数据, 为了使服务端区分不同的用户, 服务端程序引入了Session这个概念,浏览器首次请求服务端,服务端会在HTTP协议中告诉客户端,需要再Cooke里面记录一个SessionID,以后每次请求把这个SessionId发送到服务器,这样服务器就能区分不同的客户端了。
有了这样的对应关系,我们就可以在Session中保存当前用户的信息。其实我们这里只做了登录,还没有做登出,登出应该将对应的Session中清除掉。这套逻辑Shiro帮我们做好了,那自然是极好的,但仅仅是如此的话,还不足以让我们使用Shiro, 我们接着翻官方文档。
因为很久没写Servlet了,这次去下载Tomcat,下了一个10.0的, 但是发现10.0版本跟JDK 8不太兼容,折腾了许久, 请求都没办法到达Servlet,要不就是报Servlet初始化失败,最高只好退回8.5版本,但是还是发现请求到达不了我写的Servlet中, 我是基于注解的形式配置的映射,但是web.xml的有个属性我忘记了,那就是metadata-complete,
Cryptography: 加密, 其实Java标准库也提供了实现,那Shiro能提供一套更简单易用的API更好。
Authorization:授权, 这个值得我们注意一下,写到这里我想起我第一个构建的Web系统,当时只考虑了普通的用户,没有考虑资源控制的问题,当时已经快到预定的时间了,说来惭愧, 只好做了一个非常粗糙的权限控制,为用户添加了一个权限标识字段,1代表什么角色,2代表什么角色能看哪些页面,也就是说资源是固定的,相当的僵硬。后面才了解到在这方面有一套比较成熟而自然的RBAC(Role-Based Access Controle 基于角色的访问控制)模型,即角色-用户-权限(资源),也就是说一个用户拥有若干角色,每一个角色拥有若干权限和资源,这样我们就实现了权限和用户的解耦合。
基本概念我们大致论述完之后,我们来进一步深入的看这些特性:
-
-
基于主体,在Shiro中做的任何事情都基于当前正在活动的用户,在Shiro中称之为主体,你可以在代码的任何地方取到当前的主体。
这将让你在使用和理解shiro变的轻松起来。
-
简单的方法调用,非常简单,节省时间和精力。
-
丰富的异常体系,Shiro提供了完备的异常体系来解释登录为什么失败。这个异常体系可以帮助诊断定制服务的相关bug和issue。除此之外,还可以帮助创建功能更加丰富的应用。
-
记住我,标准的Shiro API提供了记录密码的功能,只需少量的配置,就能给用户提供更佳的体验。
-
可插拔的数据源,Shiro提供了一个可插拔的数据权限对象,在shiro中我们称之为Realms,我们用这个去安全的连接像LDAP、Active Directory的数据源。
为了避免开发者做重复的工作,Shiro 提供了开箱即用的连接指定数据源的Realm是,像LDAP、Active Directory 、JDBC。 如果你需要你也可以创建自定义的Realms。
-
支持一个和多个Realm登录,使用Shiro 你可以轻松的完成用户使用多个Realm登录,并且方式统一。除此之外,你也可以可以使用Shiro的身份验证策略自定义登录过程,验证策略支持写在配置文件中,所以当验证策略改变的时候,不需要更改代码。
-
看来上面的特性概述,你会发现原来登录需要考虑这么多,原先我们的视角可能只在数据库的数据源,事实上对于WEB系统来说还可以引入其他数据源,但是你不用担心,这么多需要考虑的东西,原先你自己来写登录,可能还会考虑遗漏的地方,但是Shiro都帮你写好。我们还有什么理由不学它呢。这里还是需要重点讲一下Shiro的Realms概念,我们回忆一下JDBC,可以让我们Java程序员写一套API就能做到跨数据库,那多个数据源呢,我们能否也抽象出一个接口,做到登录的时候跨数据源呢? 其实Realms就是这个思路,也抽象出了一个接口,对接不同的数据源来实现登录认证:
我们只重点介绍一个特性来体会Shiro的强大,其他特性我们只简单介绍转眼的点:
-
Java的扩展非常难用,当然你要是个密码专家就当我没说),Shiro设计的密码学的API更简单易用。
PS: 其实还指出了Java密码学扩展的一些问题,算是对Java密码学相关库的吐槽了。有兴致可以去看看,我们这里不做过多介绍。
-
可以被用于SSO,获取用户登录和退出都相当方便。SSO是单点登录,方便的和各种应用系统做集成。
-
下面是授权的几个经典问题:
这个用户是否可以编辑这个账号
这个用户是否有权限看这页面
这个用户是否有权限使用这个按钮
Shiro回答了以上问题,并且非常灵活、简单、容易使用。
Shiro帮我们做了这么多,而且简单,我们可以省了很多工作,这就是学习Shiro的理由。
Shiro核心概念概述
在Shiro中的架构中有三个主要概念:
-
subject(当前主体, 可以理解为当前登录用户,)
在Shiro中可以使用下面代码来获取当前登录用户:
为所有用户提供安全保护,内嵌了很多安全组件,那么如何设置它呢? 也取决于不同的环境, Web 程序中通常是在Web.xml中指定Shiro的Servlet过滤器,这就完成了一个SecurityManager 实例,其他类型的应用程序我们也有其他选项。
Realm 事实上是Shiro和你应用安全数据的桥梁或连接器。
首先引入maven依赖:
// 判断是否可以登录 // 这是一个简单的Realm,直接在代码里面存储账号和密码 // 用户登录和密码凭证密码学是隐藏或混淆数据的过程,防止数据被窃取。Shiro在密码学方面的目标是简化JDK标准密码学库的使用
接下来让我们下用Shiro的密码学相关的API有多简单易用.
//输出的是MD5的十六进制形式这么一看Shiro的实现确实简单一些,更直观。
在Shiro中将授权分成以下两种:
准许是安全策略的原子级别,表现为功能的声明。准许的意思是你可以在这个系统中做什么。形式良好的准许描述了资源类型以及可以对这些资源进行的操作。比如: 你是否可以打开这扇门? 你是否可以读一个文件? 你是否可以删除一个客户记录? 你是否能点击按钮?
一般来说对资源的操作有新增、读取、更新、删除,这些操作通常被称作为CRUD。
一定要理解,准许是不知道是谁可以操作这些资源的,它们只是说明这些资源可以执行哪些操作。
资源级别: 这是最广泛的而且是最容易构建的。用户可以编辑客户记录或者打开一扇门。资源指定了,但是没有指定到具体的人祸角色上。
实例级别: 某个准许指定了具体的人或者角色, 某个用户可以编辑IBM的用户记录或打开厨房的门。
属性级别: 某人被允许编辑资源的某个属性,某个用户可以编辑IVM用户记录的地址。
在授权的上下门,角色实际上是权限的集合,简化权限和用户的管理,因此用户可以被分配角色,而不是直接被分配权限,因为直接分配权限这对于更大的用户群和更复杂的应用程序来说会比较复杂。
Shiro支持如下两种角色:
大多数人的角色在我们眼中属于是隐式角色,隐含了一组权限,通常的说,如果你具有管理员的角色,你可以查看患者数据。如你具有“银行出纳员”的角色,那么你可以创建账号。
显式角色就是系统明显分配的权限,如果你可以查看患者数据,那是因为你被分配到了“管理员角色”的“查看患者数据”权限。
上面是我翻译的Shiro对角色和权限的论述,权限的话可以理解为对某个资源的CRUD, 粒度级别有整个资源,比如一行记录的操纵权限,这行记录只有某个人才能操纵,某个人只能操纵这行记录的一部分。而角色则是权限的集合, 在我看来是实现权限和用户的解耦,比如我想对一批用户授权,我可以选一个角色,进行批量授权。那么问题又来了,我该怎么做权限控制呢,或者在Shiro中判断某个是否有这个角色呢?
-
我们可以从Subject这个类的方法中判断当前用户是否具备某个角色或者具备某个权限
- JDK 的注解, 在方法中加注解
// 判断当前角色是否有admin 这个角色
// 判断当前用户是否允许添加用户
-
JSP 标签(前后端分离时代了, 这个不做介绍)
我们前面一直再说Realm是Shiro和用户数据之间的桥梁, 我们大致看下这个登录过程,重点来体会一下桥梁:
该类拥有一个Authenticator成员变量,由该成员变量调用authenticate,获取用户信息
这在某种成都上很像是模板方法模式, 父类定义骨架或通用方法,子类做调用。Authenticator是一个接口有许多实现类,但是调用的authenticate就只有两个实现:
* 我们这个自定义reamls就能实现权限控制了 // 假装这roles 是从数据库中查的 // 假装是从数据库查的 // 假装去查了数据库
我记得刚开始学Shiro的时候是去B站搜对应的视频, 但是视频大多都是从Shiro的基本组件开始讲,我其实只是想知道Shiro能帮我干啥,去看教程也是先从Shiro是一个安全框架讲起,然后讲架构,看了半天视频我只收获了一堆名词,我想看的东西都没看到,实在消耗我的耐心。所以本篇文章是以问题为导向,即Shiro最终帮我们做了什么,同时也调整了一些文章介绍风格,省略掉一些比较大的词,这篇文章献给当初在网上找Shiro,找了半天也没找到合心意的教程的自己。
-
RBAC用户、角色、权限、组设计方案
-
Shiro安全框架【快速入门】就这一篇!