授权: 又称访问控制—控制谁有权限在应用程序中做什么。在授权中,需要了解几个关键的对象:Subject 主体、Resource 资源、Permissions 权限、Role 角色:

  • Subject 主体:访问应用的用户,在 Shiro 中使用 Subject 代表该用户,用户需要授权后才能访问相应的资源
  • Resource 资源:在应用中用户访问的任何东西,例如:jsp、接口、图片等,都属于是资源
  • Permissions 权限:Shiro 安全机制最核心的元素。它在应用程序中明确声明了被允许的行为。一个格式良好的权限声明可以清晰表达出用户对该资源拥有的权限。在 Shiro 中主要通过通配符表达式来完成权限的描述
  • Role 角色:一个命名的实体, 通常代表一组行为或职责。 这些行为演化为在一个应用中能或者不能做的事情。角色通常分配给用户帐户。一个角色拥有一个权限的集合。授权验证时,需要判断当前角色是否拥有指定的权限。这种角色权限可以对该角色进行详细的权限描述。 Shiro 官方推荐使用这种方式

授权检查的例子: 用户是否能访问某个网页,编辑数据,或打使用这台打印机

授权的三要素: 权限、角色和用户 。

需要在应用程序中对用户和权限建立关联: 通常的做法是将权限分配给角色,然后将角色分配给一个或多个用户。

Shiro 的三种授权方式:

  • 编写代码:在 Java 代码中用像 if 和 else 块的结构执行授权检查。
  • JDK 的注解:可以添加授权注解给 Java 方法
  • JSP 标签库:可以控制基于角色和权限的 JSP 页面输出。

Shiro 授权顺序图:

时序图:

说明:

  • Step 1: 应用程序或框架代码调用任何 Subject 的hasRole*checkRole*isPermitted*, 或者checkPermission*方法的变体,传递任何所需的权限
  • Step 2: Subject 的实例—通常是 DelegatingSubject(或子类),调用 securityManager 的对应的方法。
  • Step 3: SecurityManager 调用 org.apache.shiro.authz.Authorizer 接口的对应方法。默认情况下,authorizer 实例是一个 ModularRealmAuthorizer 实例,它支持协调任何授权操作过程中的一个或多个 Realm 实例。
  • Step 4: 每个配置好的 Realm 被检查是否实现了相同的 Authorizer 接口。如果是,Realm 各自的 hasRole*checkRole*isPermitted*,或 checkPermission* 方法将被调用。

Shiro 基础语法:Permissions 的声明方式

基础语法之简单的字符串:

  • 即用简单的字符串来表示一个权限,如:user (相当于:user:*

基础语法之多层次管理:

  • 例如:user:query、user:edit
  • 多个值:每个部件能够保护多个值。因此,除了授予用户 user:query 和 user:edit 权限外,也可以简单地授予他们一个:user:query, edit
  • 还可以用 * 号代替所有的值,如:user:* , 也可以写:*:query,表示某个用户在所有的领域都有 query 的权限

基础语法之实例级访问控制:

  • 这种情况通常会使用三个部件:域、操作、被付诸实施的实例。如:user:edit:manager
  • 也可以使用通配符来定义,如:user:edit:*、user:*:*、user:*:manager
  • 部分省略通配符:缺少的部件意味着用户可以访问所有与之匹配的值,比如:user:edit 等价于 user:edit :*、user 等价于 user:*:*

注意: 通配符只能从字符串的结尾处省略部件,也就是说 user:edit 并不等价于 user:*:edit

Shiro 注销

logout(注销):currentUser.logout();

  • 调用 logout() 方法时,现有 Session 将失效,而且身份将失去关联(在 Web 应用程序中,RememberMe cookie 将被删除)。
  • 在 Subject 注销后,该 Subject 的实例被再次认为是匿名的。

注意:WEB 应用程序记住身份往往依靠 Cookie,然而 Cookie 只能在 Response 被返回后被删除,所以建议在调用 subject.logout() 后立即向终端重定向一个新的视图或页面。这样即能保证与安全相关的 Cookie 都能像预期的一样被删除。

Realm

  • Realm:访问应用程序安全数据(如用户、角色及权限)的组件。
  • Realm 通常和数据源是一对一的对应关系,如关系数据库、文件系统或其他类似资源。Realm 实质上就是一个访问安全数据的 DAO。
  • 数据源通常存储身份验证数据(如密码的凭证)以及授权数据(如角色或权限),所以每个 Realm 都能够执行身份验证和授权操作。

Realms 的认证实现

Shiro 的认证过程由 Realm 执行,SecurityManager 会调用 org.apache.shiro.realm.Realm 的 getAuthenticationInfo(AuthenticationToken token) 方法

实际开发中,通常会提供 org.apache.shiro.realm.AuthenticatingRealm 的实现类,并在该实现类中提供doGetAuthenticationInfo(AuthenticationToken token)方法的具体实现

  1. 检查提交的进行认证的令 ××× 信息
  2. 根据令 ××× 信息从数据源 (通常为数据库) 中获取用户信息
  3. 对用户信息进行匹配验证。
  4. 验证通过将返回一个封装了用户信息的 AuthenticationInfo 实例。
  5. 验证失败则抛出 AuthenticationException 异常信息。