继续我们shiro系列博客相关的学习笔记,各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!

目录

身份验证

示例

创建SecurityManager

验证Subject

记住我与已认证(Remembered vs. Authenticated)

为什么要区分 Remembered  Authenticated?

一个说明性的例子

Logging Out

身份验证流程

授权

权限

角色

主题

资源

授权方式

权限验证相关api

授权流程


身份验证

身份验证是身份验证的过程 - 也就是说,证明用户实际上是他们所说的人。为了让用户证明他们的身份,他们需要提供一些识别信息以及系统理解和信任的某种身份证明。

通常提供用户的principals 和credentials 给shiro来进行身份的验证。最常见的 principals 和 credentials 组合就是用户名 / 密码了。

principals:身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。一个主体可以有多个 principals,但只有一个 Primary principals,一般是用户名 /  手机号。 credentials:证明 / 凭证,即只有主体知道的安全值,如密码 / 数字证书等。

示例

在说身份验证流程前,先看一下官网提供的shiro使用样例的代码,我稍微做了下调整;

public class Quickstart {public static void main(String[] args) {//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManagerFactory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");//2、得到SecurityManager实例 并绑定给SecurityUtilsSecurityManager securityManager = factory.getInstance();//3、使SecurityManager可在整个应用里使用SecurityUtils.setSecurityManager(securityManager);//4、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)Subject currentUser = SecurityUtils.getSubject();UsernamePasswordToken token = new UsernamePasswordToken("admin", "admin123");//5、记住我token.setRememberMe(true);try {//6、登录,即身份验证currentUser.login(token);//7、判断用户角色if (currentUser.hasRole("admin")) {log.info("拥有admin角色!");} else {log.info("没有admin角色!");}//8、判断用户权限if (currentUser.isPermitted("system:user:delete")) {log.info("拥有执行删除操作的权限!");} else {log.info("没有执行删除操作的权限!");}//9、做一些其他的操作dosomething();} catch (Exception uae) {// 可能有多种异常 }//10、退出currentUser.logout();}
}

上面几步包含了使用shiro的基本操作过程,结合下面官方身份验证流程图来看,我们要进行身份验证,最起码应该有SecurityManager和验证通过的Subject,有了SecurityManager才能管理我们的Subject、才能进行认证。

创建SecurityManager

上面使用Ini配置文件初始化SecurityManager,并通过工厂的factory.getInstance()方法获来得到SecurityManager实例,除了这种方式之外还有更简单常用的一种方式:

Realm realm = // 实例化或获得一个Realm 的实例,稍后讨论Realm。
SecurityManager securityManager = new DefaultSecurityManager(realm);
// 使SecurityManager可在整个应用里使用
SecurityUtils.setSecurityManager(securityManager);

验证Subject

验证主题的过程可以分为三个步骤:

1、收集主题提交的身份和凭证

//示例使用最常见的用户名/密码对场景:UsernamePasswordToken token = new UsernamePasswordToken(username, password);

2、提交主题的身份和凭证进行身份验证。

Subject currentUser = SecurityUtils.getSubject();
currentUser.login(token);

3、如果提交成功,则允许访问,否则重试身份验证或阻止访问。

try {currentUser.login(token);
} catch ( UnknownAccountException uae ) { ...
} catch ( IncorrectCredentialsException ice ) { ...
} catch ( LockedAccountException lae ) { ...
} catch ( ExcessiveAttemptsException eae ) { ...
} ... catch your own ...
} catch ( AuthenticationException ae ) {//unexpected error?
}

记住我与已认证(Remembered vs. Authenticated)

如上例所示,除了正常的登录过程,Shiro 还支持“记住我”的概念。此时值得指出的是,Shiro 对记住的Subject 和实际经过验证的Subject做了非常精确的区分:

  • Remembered :记住的主题不是匿名的,并且具有已知的身份(即,subject.getPrincipals() 是非空的)。 但是这个身份是在前一个会话期间从前一个身份验证中记住的。 如果 subject.isRemembered() 返回 true,则认为主题已被记住。
  • Authenticated:经过身份验证的主题是在主题的当前会话期间已成功通过身份验证的主题(即调用 login 方法时未引发异常)。 如果 subject.isAuthenticated() 返回 true,则认为主题已通过身份验证。

记住状态和已验证状态是互斥的 - 一个为真另一个必为假,反之亦然。

为什么要区分 Remembered  Authenticated?

“认证”一词具有很强的证明含义。也就是说,有一个预期的保证,即主体已经证明他们就是他们所说的那样。

当用户只从之前与应用程序的交互中被记住时,证明状态不再存在:记住的身份让系统知道该用户可能是谁,但实际上,无法绝对保证记住的主题代表预期的用户。

因此,尽管应用程序的许多部分仍然可以根据记住的主体执行用户特定的逻辑,例如自定义视图,但它通常不应该执行高度敏感的操作,直到用户通过执行成功的身份验证尝试合法地验证了他们的身份。

例如,检查主体是否可以访问财务信息应该几乎总是依赖于 isAuthenticated(),而不是 isRemembered(),以保证预期的和经过验证的身份。

一个说明性的例子

以下是一个相当常见的场景,有助于说明为什么记住和验证之间的区别很重要。

假设您正在使用 淘宝购物。您已成功登录并已将几本书添加到您的购物车中。但是要去开会,但忘记注销。会议结束时,该回家了,离开办公室。

第二天上班时,您意识到您没有完成购买,因此您返回 淘宝。这一次,淘宝记住了你是谁,不用再输入用户名密码进行登录就可以访问网站,对于淘宝,subject.isRemembered() 将返回 true。

但是,如果您尝试访问您的帐户以更新您的信用卡信息以购买图书,会发生什么情况?虽然淘宝“记住”了您(isRemembered() == true),但它不能保证您确实是您(例如,也许一位同事正在使用您的计算机)。

因此,在您执行更新信用卡信息等敏感操作之前,淘宝会强制您登录,以便他们保证您的身份。登录后,您的身份已通过验证,对于 淘宝,isAuthenticated() 现在将变为 true。

对于许多类型的应用程序,这种情况经常发生,因此该功能内置于 Shiro 中,因此您可以将其用于您自己的应用程序。现在,您是否使用 isRemembered() 或 isAuthenticated() 来自定义您的视图和工作流取决于您,但 Shiro 将在您需要时保持这种基本状态。

Logging Out

currentUser.logout();

当您调用注销时,任何现有的会话将无效,任何身份将被解除关联(例如,在web应用程序中,RememberMe cookie也将被删除)。

身份验证流程

官网身份验证流程图:

流程如下:

1、首先调用 Subject.login(token) 进行登录,其会自动委托给 Security Manager,调用之前必须通过 SecurityUtils.setSecurityManager() 设置;

2、SecurityManager 负责真正的身份验证逻辑;它会委托给 Authenticator 进行身份验证;

3、Authenticator 才是真正的身份验证者,Shiro API 中核心的身份认证入口点,此处可以自定义插入自己的实现;

4、Authenticator 可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证,默认 ModularRealmAuthenticator 会调用 AuthenticationStrategy 进行多 Realm 身份验证;

5、Authenticator 会把相应的 token 传入 Realm,从 Realm 获取身份验证信息,如果没有返回 / 抛出异常表示身份验证成功了。此处可以配置多个 Realm,将按照相应的顺序及策略进行访问。

授权

授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作等)。在授权中需了解的几个关键对象:主体(Subject)、资源(Resource)、权限(Permission)、角色(Role)。

权限

安全策略中的原子授权单位,通过权限我们可以表示在应用中用户有没有操作某个资源的权力。即权限表示在应用中用户能不能访问某个资源。

权限代表了用户有没有操作某个资源的权利,即反映在某个资源上的操作允不允许,不反映谁去执行这个操作。所以后续还需要把权限赋予给用户,即定义哪个用户允许在某个资源上做什么操作(权限)。

角色

隐式角色: 即直接通过角色来验证用户有没有操作权限,粒度是以角色为单位进行访问控制的,粒度较粗,如果进行修改可能造成多处代码修改。

如在应用中 CTO、技术总监、开发工程师可以使用打印机,假设某天不允许开发工程师使用打印机,此时需要从应用中删除相应代码;再如在应用中 CTO、技术总监可以查看用户、查看权限;突然有一天不允许技术总监查看用户、查看权限了,需要在相关代码中把技术总监角色从判断逻辑中删除掉。

显示角色: 在程序中通过权限控制谁能访问某个资源,角色聚合一组权限集合,粒度是以资源/实例为单位的,粒度较细。这样假设哪个角色不能访问某个资源,只需要从角色代表的权限集合中移除即可;无须修改多处代码。

主题

即访问应用的用户,在 Shiro 中使用 Subject 代表该用户。用户只有授权后才允许访问相应的资源。

资源

在应用中用户可以访问的URL,比如访问 JSP 页面、查看/编辑某些数据、访问某个业务方法、打印文本等等都是资源。

授权方式

Shiro 支持三种方式的授权:

编程式:通过写 if/else 授权代码块完成:

Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {//有权限
} else {//无权限
}

注解式:通过在执行的 Java 方法上放置相应的注解完成,没有权限将抛出相应的异常:

@RequiresRoles("admin")
public void hello() {//有权限
}

JSP/GSP 标签:在 JSP/GSP 页面通过相应的标签完成:

<shiro:hasRole name="admin">
<!— 有权限 —>
</shiro:hasRole>

权限验证相关api

hasRole/hasRoles:用于判断用户是否拥有某个角色/某些权限;但是没有提供如 hashAnyRole 用于判断是否有某些权限中的某一个。

checkRole/checkRoles: 和hasRole/hasRoles不同的地方是它在判断为假的情况下会抛出 UnauthorizedException 异常。

isPermitted/isPermittedAll: 用于判断用户是否拥有某个权限或所有权限,也没有提供如 isPermittedAny 用于判断拥有某一个权限的接口。

授权流程

流程如下:

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 匹配流程等请参考 官方文档 和 w3cschool 。

Shiro系列(三)--- Shiro身份验证和授权相关推荐

  1. shiro系列二、身份验证和授权

    一.身份验证 先来看看身份验证的流程 流程如下: 1.首先调用Subject.login(token)进行登录,其会自动委托给Security Manager,调用之前必须通过SecurityUtil ...

  2. etcd入门系列三:身份验证访问控制

    etcd入门系列 一. etcd在docker中的安装与使用 二. etcd 开启 https 1. 简介 etcd 默认是没有开启访问控制的,如果我们开启外网访问的话就需要考虑访问控制的问题,etc ...

  3. 开源软件加密授权方案_身份验证和授权作为开源解决方案服务

    开源软件加密授权方案 通过实施身份验证和授权(a&a)机制为所有用户数据设计集中式服务. 我将分享我的经验并最终确定解决方案的结论. 该设计包括客户端(Web应用程序)和服务器(A&A ...

  4. 身份验证和授权作为开源解决方案服务

    通过实施身份验证和授权(a&a)机制为所有用户数据设计集中式服务. 我将分享我的经验并最终确定解决方案的结论. 该设计包括客户端(Web应用程序)和服务器(A&A中心). 术语: 1. ...

  5. 使用kubectl访问Kubernetes集群时的身份验证和授权

    全栈工程师开发手册 (作者:栾鹏) 架构系列文章 kubectl是日常访问和管理Kubernetes集群最为常用的工具. 当我们使用kubeadm成功引导启动(init)一个Kubernetes集群的 ...

  6. Asp.net 身份验证、授权概述

    [本周]如约而至;时间是争取来的,这回的[本周]是把若干零碎的时间利用起来成文的,完成对Asp.net身份验证.访问授权等内容的梳理,可能漏掉的东西会比较多,漏掉的还是希望大家来补充.顺便说一下上次[ ...

  7. 使用JWT的ASP.NET CORE令牌身份验证和授权(无Cookie)——第2部分

    目录 介绍 用户角色 如何创建自定义授权特性? AuthorizeAttribute AuthorizeFilter 如何在控制器和操作方法级别设置权限? 检查用户权限的扩展方法 如何在操作方法(内联 ...

  8. 说说Asp.net 身份验证、授权

    观其大略: 1.       Asp.net 是依存于 IIS 的一个服务,说到 Asp.net 的安全相关的话题当然要有一个整体上的思路: IIS 接收 - > IIS 验证 - > I ...

  9. 【.NET框架实战】IdentityServer4身份验证、授权

    [.NET框架实战]IdentityServer4身份验证.授权 什么是身份认证 身份认证是指当客户端访问服务端资源时,验证客户端是否合法的一种机制 什么是授权 授权就是指当客户端经过身份认证后,能够 ...

最新文章

  1. 南海有macbook吗?
  2. UVA10970大块巧克力
  3. QT的QGraphicsView类的使用
  4. 黑马程序员-面向对象-06天-5(单例设计模式)
  5. 手机控制linux工具下载,Scrcpy-Scrcpy(手机控制软件)下载 v1.16官方版--pc6下载站
  6. 在计算机网络应用发展过程中 被称为,计算机网络技术与应用第三章考试题
  7. 急性中耳炎的治疗行业调研报告 - 市场现状分析与发展前景预测
  8. Happy Necklace
  9. 拉扎维对于简单CMOS电路的增益计算方法
  10. 最好用的U盘数据恢复软件是哪个,迅龙U盘数据恢复软件
  11. 学习:Ubuntu14.04编译caffe问题记录
  12. 详解MOVE PROTOCOL的测试版,让健康运动如影随形
  13. 使用SendCloud企业发送邮件
  14. 1 进 2 出 HDMI 1.4 分配器,带 HDCP 引擎、抖动清除和信号中继
  15. uni-app学习笔记--浏览vue-cli创建uni-app模板的文件结构
  16. 初识html及工具的使用
  17. GNS3实验操作(三)
  18. 小白前端学习流程【爱创课堂专业前端培训】
  19. 29_ElasticSearchIK中文分词器的安装和使用
  20. python 白噪声检验-使用python实现时间序列白噪声检验方式

热门文章

  1. python画roc曲线需要什么数据_python sklearn画ROC曲线
  2. Trias联合创始人陈旭明出席2019全球数字经济论坛会议
  3. 小程序 仿电话加密 例:132****9999
  4. ubuntu14.04下好用的英汉词典
  5. linux设定vnc锁屏时间,3. 设置VNC和时间同步
  6. 基于物联网操作系统HelloX的智慧家庭体系架构
  7. 视频剪辑,教你最简单的方法转换视频格式
  8. php 网站日志分析,网站日志数据分析
  9. PD3.0协议层 第四章控制消息
  10. html css hack