自己建服务类收费网站要多少钱,合肥优化,购物网页代码,网站建设与经营引言
以此篇博客为引#xff0c;开启一个新的专栏分类——Shiro。
之前在工作中有比较快速的学习过Shiro安全框架#xff0c;但经过一年的荒废#xff0c;已经不是很熟悉了#xff0c;通过这个系列#xff0c;深入研究和学习Shiro的一些知识#xff0c;填补安全管理方面…引言
以此篇博客为引开启一个新的专栏分类——Shiro。
之前在工作中有比较快速的学习过Shiro安全框架但经过一年的荒废已经不是很熟悉了通过这个系列深入研究和学习Shiro的一些知识填补安全管理方面的知识漏洞。使我们在web 开发领域更具竞争力不做只会CRUD的程序员
一、Shiro介绍
Shiro是一个Java安全框架执行身份验证、授权、密码、会话管理。Shiro是Apache 的一个开源项目前身是JSecurity 项目始于2003年初。
Shiro 可以为任何应用提供安全保障 - 从命令行应用、移动应用到大型网络及企业应用。
shiro 解决了应用安全的四要素 认证 - 用户身份识别常被称为用户“登录”授权 - 访问控制密码加密 - 保护或隐藏数据防止被偷窥会话管理 - 每用户相关的时间敏感的状态。同时Shiro另外支持了一些辅助特性如 Web 应用安全、单元测试和多线程它们的存在强化了上面提到的四个要素。
二、Shiro的优势
从 2003 年至今框架选择方面的情况已经改变了不少但今天仍有令人信服的理由让你选择 Shiro。其实理由相当多Apache Shiro
1、易于使用 - 易用性是这个项目的最终目标。应用安全有可能会非常让人糊涂令人沮丧并被认为是“必要之恶”【译注比喻应用安全方面的编程。】。若是能让它简化到新手都能很快上手那它将不再是一种痛苦了。
2、广泛性 - 没有其他安全框架可以达到 Apache Shiro 宣称的广度它可以为你的安全需求提供“一站式”服务。
3、灵活性 - Apache Shiro 可以工作在任何应用环境中。虽然它工作在 Web、EJB 和 IoC 环境中但它并不依赖这些环境。Shiro 既不强加任何规范也无需过多依赖。
4、Web 能力 - Apache Shiro 对 Web 应用的支持很神奇允许你基于应用 URL 和 Web 协议如 REST创建灵活的安全策略同时还提供了一套控制页面输出的 JSP 标签库。
5、可插拔 - Shiro 干净的 API 和设计模式使它可以方便地与许多的其他框架和应用进行集成。你将看到 Shiro 可以与诸如 Spring、Grails、Wicket、Tapestry、Mule、Apache Camel、Vaadin 这类第三方框架无缝集成。
6、支持 - Apache Shiro 是 Apache 软件基金会成员这是一个公认为了社区利益最大化而行动的组织。项目开发和用户组都有随时愿意提供帮助的友善成员。
三、核心概念
Shiro的核心概念有三个SubjectSecurityManager 和 Realms。
3.1 Subject
subject 被Shiro 描述为一个主体对于web应用来说可以简单理解为用户。
这里我们来阐述一个Shiro设计的重要理念即以主体为展开的安全体系构建。引用一段话 在考虑应用安全时你最常问的问题可能是“当前用户是谁”或“当前用户允许做 X 吗”。当我们写代码或设计用户界面时问自己这些问题很平常应用通常都是基于用户故事构建的并且你希望功能描述和安全是基于每个用户的。所以对于我们而言考虑应用安全的最自然方式就是基于当前用户。Shiro 的 API 用它的 Subject 概念从根本上体现了这种思考方式。 在应用程序中我们可以在任何地方获取当前操作的用户主体
import org.apache.shiro.subject.Subject;
import org.apache.shiro.SecurityUtils;
...
Subject currentUser SecurityUtils.getSubject();
获得Subject 后通过这个对象我们可以对其进行绝大多数安全操作登录、登出、访问会话、执行授权检查等。
Shiro 的api非常直观它反映了开发者以“每个用户” 思考安全控制的自然趋势。
3.2 SecurityManager
Subject 的幕后推手是 SecurityManagerSubject 代表了当前用户的安全操作SecurityManager则管理所有用户的安全操作。 SecurityManager 是 Shiro 框架的核心充当“保护伞”引用了多个内部嵌套安全组件它们形成了对象图。但是一旦 SecurityManager 及其内部对象图配置好它就会退居幕后应用开发人员几乎把他们的所有时间都花在 Subject API 调用上。 一个应用只需要一个 SecurityManager是一个单例对象。它的缺省实现是POJOShiro 里的其他组件也是一样。因此可以用POJO兼容的任何配置机制进行配置普通的Java代码、Spring xml、YAML、和 ini 文件等。基本上能够实例化类和调用JavaBean兼容方法的任何配置形式都可以。
比如通过ini文件进行配置
[main]
cm org.apache.shiro.authc.credential.HashedCredentialsMatcher
cm.hashAlgorithm SHA-512
cm.hashIterations 1024
# Base64 encoding (less text):
cm.storedCredentialsHexEncoded falseiniRealm.credentialsMatcher $cm
[main] 段落是配置SecurityManager 对象及其使用的其他任何对象如 Realm 的地方在上面的示例中我们看到了两个对象
1、cm对象是Shiro 的HashedCredentialsMatcher 类实例cm 的各属性通过“嵌套点”语法进行配置。
2、iniRealm对象被 SecurityManager 用来表示以INI 格式定义的用户账户。
然后我们在Java代码中可以轻而易举的获得 SecurityManager对象了
//1. 装入 INI 配置
FactorySecurityManager factory new IniSecurityManagerFactory(classpath:shiro.ini);//2. 创建 SecurityManager
SecurityManager securityManager factory.getInstance();//3. 使其可访问
SecurityUtils.setSecurityManager(securityManager);
3.3 Realm
Realm 充当了 Shiro 与应用安全数据间的“桥梁”或者“连接器”。当切实与像用户帐户这类安全相关数据进行交互执行认证登录和授权访问控制时Shiro 会从应用配置的 Realm 中查找很多内容。
从某种意义上讲Realm 实际上就是一个安全相关的 DAO它封装了数据源的连接细节并在需要时将相关数据提供给 Shiro。
注意在配置Shiro 时必须指定至少一个 Realm 可以配置多个。
Shiro 内置了一些Realm 支持多种数据源的连接如JDBC、LDAP、INI文件的连接等。另外可以自定义Realm 实现方便个性化的应用场景。
四、典型的安全场景概述
应用安全的四要素认证、授权、会话管理、加密。
4.1 认证
虽然有些武断但是一般web 应用认证就是登录功能。也就是说当用户使用应用进行认证时他们就在证明他们就是自己所说的那个人。
这是一个典型的三步过程 1、收集用户身份信息成为当事人principal以及身份的支持证明称为证书Credential。 2、将当事人和证书提交给系统。 3、如果提交的证书与系统期望的该用户身份当事人匹配该用户就被认为是经过认证的反之则被认为未经认证的。 Shiro 以简单直观的方式支持同样的流程。Shiro 有一套以Subject 为中心的API几乎你想要用 Shiro 在运行时完成的所有事情都能通过与当前执行的 Subject 进行交互而达成。因此要登录 Subject只需要简单地调用它的 login 方法。传入表示被提交当事人和证书在这种情况下就是用户名和密码的 AuthenticationToken 实例。
//1. 接受提交的当事人和证书
AuthenticationToken token
new UsernamePasswordToken(username, password);//2. 获取当前 Subject
Subject currentUser SecurityUtils.getSubject();
//3. 登录
currentUser.login(token);
可以看到Shiro的操作及其简洁和自然这也是Shiro 惯有的风格。在调用 login(方法后SecurityManager 会收到AuthenticationToken并将其发送给已配置的 Realm执行必须的认证检查以往我们手动去数据库中进行校验和匹配的时代已经过去了这些所有的操作全部由Shiro 帮我们自动完成。当数据经过Realm 的检查后发现无法匹配那么Shiro 就会返回 AuthenticationException 异常的子类通过这些子类我们可以精确的控制想要返回给用户的错误信息
try {currentUser.login(token);
} catch (IncorrectCredentialsException ice) {…
} catch (LockedAccountException lae) {…
}
…
catch (AuthenticationException ae) {…
}
如果没有抛出任何异常则证明 Subject 登录成功就被认为是已认证的。
4.2 授权
授权实质上就是访问控制控制已认证的用户能够访问应用的哪些内容如资源、页面等。
多数用户执行访问控制是通过 角色 权限 的概念来完成的。角色是所有用户个体的一个分组如管理员、普通用户、商家等而权限 则表示具体能够操作的行为比如查询所有用户、删除某些用户、修改信息等等是与具体应用资源直接挂钩的。
用户、角色和 权限三者往往通过 角色 来进行转换用户和权限之间通常不进行直接绑定 我们可以通过shiro的校验方法来便捷地实现分支语句
if ( subject.hasRole(administrator) ) {// 显示‘Create User’按钮
} else {// 按钮置灰?
}
虽然在概念上权限与角色直接挂钩但其最终效果还是要落实到具体的某个用户是否具有某个权限为此Shiro也为我们提供了相应的校验方法
if ( subject.isPermitted(user:create) ) {// 显示‘Create User’按钮
} else {// 按钮置灰?
}
这样任何具有“user:create”权限的角色或用户都可以点击‘Create User’按钮并且这些角色和指派甚至可以在运行时改变这给你提供了一个非常灵活的安全模型。
上例中user:create 字符串是一种遵循特定规则的权限描述符这在后面的文章中会单独介绍。具体详情可了解http://shiro.apache.org/permissions.html
上面这些权限的调用最终都会发送到SecurityManager中它会咨询 Realm 做出自己的访问控制决定。必要时还允许单个 Realm 同时响应认证和授权操作。
4.3 会话管理
在以往的Servlet应用中我们最常使用的会话对象就是 HttpSession 对象。
在Shiro 中也有属于自己的会话管理机制和用户的会话对象。Shiro 允许开发者在任何应用或架构层一致地使用 Session API。 它为任何应用从小型后台独立应用到大型集群 Web 应用提供了一个会话编程范式。这意味着那些希望使用会话的应用开发者不必被迫使用 Servlet 或 EJB 容器了。或者如果正在使用这些容器开发者现在也可以选择使用在任何层统一一致的会话 API取代 Servlet 或 EJB 机制。 Shiro 会话最重要的一个好处或许就是它们是独立于容器的。这个特性的作用非常巨大设想一下会话集群。对集群会话来讲支持容错和故障转移有多少种容器特定的方式Tomcat 的方式与 Jetty 的不同而 Jetty 又和 Websphere 不一样等等。但通过 Shiro 会话你可以获得一个容器无关的集群解决方案。 Shiro 的架构允许可插拔的会话数据存储如企业缓存、关系数据库、NoSQL 系统等。这意味着只要配置会话集群一次它就会以相同的方式工作跟部署环境无关 - Tomcat、Jetty、JEE 服务器或者独立应用。不管如何部署应用毋须重新配置应用。 获取当前用户的Session 对象我们可以使用下面这样的方法
Session session subject.getSession();
Session session subject.getSession(boolean create);
上面这些方法在概念上等同于HttpServletRequest API。第一个方法会返回 Subject 的现有会话或者如果还没有会话它会创建一个新的并将之返回。第二个方法接受一个布尔参数这个参数用于判定会话不存在时是否创建新会话。一旦获得 Shiro 的会话你几乎可以像使用 HttpSession 一样使用它。Shiro 保留的 HttpSession 的使用体验但不同的是 Shiro 可以在任何应用中使用会话机制不仅限于Web应用。
Shiro Session 的一些方法
Session session subject.getSession();
session.getAttribute(key, someValue);
Date start session.getStartTimestamp();
Date timestamp session.getLastAccessTime();
session.setTimeout(millis); ...
4.4 加密
在加密方面Shiro 尽可能的简化加密处理的步骤并让JDK的加密支持可用。
注意一点加密并不是特定于Subject 的加密的特性是 Shiro 的一部分但不特定于仅仅对 Subject 的处理。我们可以在任何地方使用 Shiro 的加密支持甚至在不使用 Subject 的情况下。
对于加密支持Shiro 真正关心的两个领域是加密哈希又名消息摘要和加密密码。
传统的JDK加密操作过于复杂而且是基于笨拙的工厂静态方法api它并不是面向对象的设计
try {MessageDigest md MessageDigest.getInstance(MD5);md.digest(bytes);byte[] hashed md.digest();
} catch (NoSuchAlgorithmException e) {e.printStackTrace();
}
如果在某些场景下频繁会用到哈希加密的情况那么开发者就必须要封装之后才能比较轻松的使用JDK 的加密支持否则将会是一个不小的工作量。Shiro 为我们提供了这样的便捷对于类似的功能只需要简单的几行代码就可以完成同时也省去了一些老旧的和不必要的异常捕获
// 面向对象的MD5加密方式
String hex new Md5Hash(myFile).toHex();
// SHA-512
String encodedPassword new Sha512Hash(password, salt, count).toBase64();
刚刚提到的这些是一些必要的哈希算法API另一个Shiro 关心的事情就是 加密密码。
我们知道加密是使用密钥对数据进行可逆转换的加密算法。我们使用其保证数据的安全尤其是传输或存储数据时以及在数据容易被窥探的时候。
同样 JDK 的加密API也非常复杂和难用而Shiro 通过引入它的 CipherService API 试图简化加密密码的整个概念。 CipherService 是多数开发者在保护数据时梦寐以求的东西简单、无状态、线程安全的 API能够在一次方法调用中对整个数据进行加密或解密。你所需要做的只是提供你的密钥就可根据需要加密或解密。 AesCipherService cipherService new AesCipherService();
cipherService.setKeySize(256);// 创建一个测试密钥
byte[] testKey cipherService.generateNewKey();
// 加密文件的字节
byte[] encrypted cipherService.encrypt(fileBytes, testKey);
较之 JDK 的 Cipher APIShiro 的示例要简单的多 你可以直接实例化一个 CipherService - 没有奇怪或让人混乱的工厂方法Cipher 配置选项可以表示成 JavaBean - 兼容的 getter 和 setter 方法 - 没有了奇怪和难以理解的“转换字符串”加密和解密在单个方法调用中完成没有强加的 Checked Exception。如果愿意可以捕获 Shiro 的 CryptoException。Shiro 的 CipherService API 还有其他好处如同时支持基于字节数组的加密 / 解密称为“块”操作和基于流的加密 / 解密如加密音频或视频。
五、Web支持
Shiro 附带了一个帮助保护web应用的强健的web 支持模块就目前大火的spring boot框架除了配置基本的依赖和Shiro 的核心单例组件 - SecurityManager 之外可能剩下的就只是要配置一个Shiro Servlet 过滤器了。
关于Shiro 的过滤器后面的文章还会详细介绍总之当我们完成了 这些前期的必要的配置工作后Shiro Filter 就会过滤每个请求并确保在请求期间特定的 Subject 是可访问的。同时由于它过滤了每个请求你可以执行安全特定的逻辑以保证只有满足一定标准的请求才被允许通过。
5.1 URL 过滤器
Shiro 通过其创新的 URL 过滤器链功能支持安全特定的过滤规则。
[urls]
/assets/** anon
/user/signup anon
/user/** user
/rpc/rest/** perms[rpc:invoke], authc
/** authc
请不要在意这些配置形式感受它所代表的含义和强大的特性内核。
对于每一行等号左边的值表示相对上下文的 Web 应用路径。等号右边的值定义了过滤器链 - 一个逗号分隔的有序 Servlet 过滤器列表它会针对给出的路径进行执行。每个过滤器都是普通的 Servlet 过滤器你看到的上面的过滤器名字anonuserpermsauthc是 Shiro 内置的安全相关的特殊过滤器。你可以搭配这些安全过滤器来创建高度定制的安全体验。你还可以指定任何其他现有的 Servlet 过滤器。
5.2 Web 会话管理
对于 Web 应用Shiro 缺省将使用我们习以为常的 Servlet 容器会话作为其会话基础设施。即当你调用 subject.getSession() 和 subject.getSession(boolean) 方法时Shiro 会返回 Servlet 容器的 HttpSession 实例支持的 Session 实例。
这种方式的曼妙之处在于调用 subject.getSession() 的业务层代码会跟一个 Shiro Session 实例交互 - 还没有“认识”到它正跟一个基于 Web 的 HttpSession 打交道。这在维护架构层之间的清晰隔离时是一件非常好的事情。
另外当需要使用与容器无关的会话特性时我们也可以开启Shiro 的原生会话管理。不同于传统的HttpServletRequest.getSession()和 HttpSession API只能和Servlet 容器打交道Shiro的原生会话管理依然可以让用户使用相同的 HTTPServletRequest 和 HttpSession 调用完成与原生会话的协作而不需要重构这些代码。这是因为 Shiro 完整实现了 Servlet规范中的 Session 部分以在 Web 应用中支持原生会话因此开发者的所有 HTTPSession 的调用都会被委托给 Shiro 内部的原生会话 API。
六、附加特性
Apache Shiro 框架还包含有对保护 Java 应用非常有用的其他特性如 为维持跨线程的 Suject 提供了线程和并发支持支持 Executor 和 ExecutorService为了将执行逻辑作为一种特殊的 Subject支持 Callable 和 Runnable 接口为了表现为另一个 Subject 的身份支持“Run As”比如在管理应用中有用支持测试工具这样可以很容易的对 Shiro 的安全代码进行单元测试和集成测试。七、框架的局限
如下是 Shiro 还未解决但是值得知道的 虚拟机级别的问题Apache Shiro 当前还未处理虚拟机级别的安全比如基于访问控制策略阻止类加载器中装入某个类。然而Shiro 集成现有的 JVM 安全操作并非白日做梦 - 只是没人给项目贡献这方面的工作。多阶段认证目前Shiro 不支持“多阶段”认证即用户可能通过一种机制登录当被要求再次登录时使用另一种机制登录。这在基于 Shiro 的应用中已经实现但是通过应用预先收集所有必需信息再跟 Shiro 交互。这个功能在 Shiro 的未来版本中非常有可能得到支持。Realm 写操作目前所有 Realm 实现都支持“读”操作来获取验证和授权数据以执行登录和访问控制。诸如创建用户帐户、组和角色或与用户相关的角色组和权限这类“写”操作还不支持。这是因为支持这些操作的应用数据模型变化太大很难为所有的 Shiro 用户强制定义“写”API。八、总结
Apache Shiro 是一个功能齐全、健壮、通用的 Java 安全框架你可以用其为你的应用护航。通过简化应用安全的四个领域即认证、授权、会话管理和加密在真实应用中应用安全能更容易被理解和实现。Shiro 的简单架构和兼容 JavaBean 使其几乎能够在任何环境下配置和使用。附加的 Web 支持和辅助功能比如多线程和测试支持让这个框架为应用安全提供了“一站式”服务。
鸣谢
《让 Apache Shiro 保护你的应用》