授权的核心:用户(user)、角色(role)、权限(permission)
权限是 shiro 安全政策中最基础的元素。
权限从根本上作出了对行为的声明,明确表示可以在应用程序中做什么。一个格式良好的权限声明基本上描述了资源以及当 Subject 与这些资源进行交互时可能出现的行为。
举例子:
角色是一个命名的实体,通常代表一组行为或职责。这些行为演化为在一个应用程序中能或者不能做的事情。
角色通常是分配给用户帐户的,因此,通过分配,用户能够“做” (被授予权限 permission) 的事情可以归属于各种角色。
正如之前所说,Subject 是 Shiro 的“用户”概念。通过给 Subject 角色或权限,允许用户(Subject)在应用程序中执行某些操作。
前提是,应用程序的数据模型定义了 Subject 是被允许做什么、不被允许做什么。
你的 realm 就是告诉 Shiro 存在哪些角色或权限。
自己实现的 Realm 是与你自己的数据源进行通信的。
你自己在数据源上定义授权模型。
在 Shiro 中执行授权可以有 3 种方式:
(可以从文档里找到详细说明)
Realm 是一个能够访问应用程序特定的安全数据(如用户、角色及权限)的组件。Realm 将应用程序特定的数据转换成一种 Shiro 能够理解的格式,这样 Shiro 能够提供一个单一的易理解的 Subject 编程 API,无论有多少数据源存在或你应用程序特定的数据是怎样的。
Realm 通常和数据源是一对一的对应关系,如关系数据库,LDAP 目录,文件系统,或其他类似资源。因此,Realm 接口的实现使用数据源特定的 API 来展示授权数据(角色,权限等),如 JDBC,文件 IO,Hibernate 或 JPA,或其他 数据访问 API。
Realm 实质上就是一个特定安全的 DAO 。因为这些数据源大多通常存储身份验证数据(如密码的凭证)以及授权数据(如角色或权限),每个 Shiro Realm 能够执行身份验证和授权操作。
若 Realm 支持一个提交的 AuthenticationToken,那么 Authenticator 将会调用该 Realm 的 getAuthenticationInfo(token) 方法。这有效地代表了一个与 Realm 的后备数据源的授权尝试。该方法按以下方法进行:
这是对所有 Realm getAuthenticationInfo 实现的最高级别的工作流。在此方法中,Realm 可以自由地做任何它们想做 的,如记录在审计日志的尝试,更新数据记录,或任何其他可以对该数据存储的身份验证尝试有意义的东西。
直接实现 Realm 接口可能导致时间消耗及错误。大多数人民选择 AuthorizingRealm 抽象类的子类而不是从头开始。 这个类实现了常用的 authentication 及 authorization 工作流来节省你的时间和精力。
将提交的 credentials 与存储在后备数据源中的 credentials 相匹配,是每个 Realm 的责任(提交的 credentials 未被加密,不能直接与数据源中的 credentials 相匹,这也引出了下面为何会有 ”CredentialsMatcher“),而不是 Authenticator 的责任。
每个 Realm 拥有有关私人信息的 credentials 格式,能够存储 credentials 及执行详细的匹配, 然而 Authenticator 只是一个普通的工作量组件。
credentials 的匹配过程在所有应用程序中几乎一样,通常不一样的是进行比较的数据。
为了确保该过程是可插入及可定制的,如果需要的话,AuthenticatingRealm 及它的子类支持 CredentialsMatcher 来执行 credentials 对比的概念。
在发现帐户数据后,它以及提交的 AuthenticationToken 用来代表一个 CredentialsMatcher 来判断所提交的 credentials 是否匹配所存储的 credentials。
Shiro 拥有某些可以让你立即使用的 CredentialsMatcher 实现,如 SimpleCredenticalsMatcher 和 HashedCredentialsMatcher
Shiro 立即可用的 Realm 的实现默认使用 SimpleCredentialsMatcher。SimpleCredentialsMatcher 为提交的 credentials 与存储在后备数据源中的 credentials 执行直接平等检查。
例如,若一个 UsernamePasswordToken 被提交后,则 SimpleCredentialsMatcher 验证该密码实际上是否与存储在数据库中的密码相同。(credential 未被加密,安全性大大丢失)
SimpleCredentialsMatcher 不仅仅为字符串执行直接相等比较。它能够处理大多数常用的字节码,像字符串,字符数 组,字节数组,文件及输入流。
Shiro 可用的 Realm 的实现可使用 HashedCredentialsMatcher。它为提交的 credentials 与存储在后备数据源中的 credentials 执行哈希加密后,再检查。
Shiro 提供了多个 HashedCredentialsMatcher 子类实现。你必须在你的 realm 中配置指定的实现来匹配你 hash 化你用 户 credentials 时使用的哈希算法。
(文档给出的是用 ini 文件实现 HashedCredentialsMatcher 子类)
Subject currentUser = SecurityUtils.getSubject();
Session session = currentUser.getSession();
session.setAttribute("someKey", someValue);
subject.getSession()方法是调用 currentUser.getSession(true)的快捷方式。
Subject.getSession(boolean create)方法与 HttpServletRequest.getSession(boolean create)方法有着异曲同工之效。
SessionManager 在应用程序中为所有的 subject 管理 Session—— 创建,删除,inactivity(失效)及验证,等等。
SessionManager 是一个由 SecurityManager 维护的顶级组件。
默认的 SecurityManger 实现是默认使用立即可用的 DefaultSessionManager。DefaultSessionManager 的实现提供一个 应用程序所需的所有企业级会话管理,如 Session 验证,orphan cleanup,等等。这可以在任何应用程序中使用(毕竟 shiro session 可以在任何应用程序中工作)。
Shiro 的 SessionManager 默认超时时间是 30 分钟。
设置 SessionManager 的 globalSessionTimeout 属性为所有的会话定义默认的超时时间;也可以为每个 session 单独的设置超时时间(session.setTimeout(long i))。
Shiro 支持的 SessionListener 允许你对发生改变的重要会话作出反应。
实现 SessionListener 接口(或扩展易用的 SessionListenerAdapter)对相应的会话操作作出反应。由于默认的 SessionManager sessionListeners 属性是一个集合,可以对 SessionManager 配置一个或多个 listener。
写在最后的话:这里的进度大概是文档内容的 2/3 或 3/4,剩下部分觉着就使用并对 shiro 有一个大概的了解的目的而言,不是”太重要“ 了。如果以后需要再读(学习)吧。