Shiro权限框架使用和原理分享

背景

目前比较流行的权限框架有Apache Shiro和 Spring Security。相比Spring Secrity, Shiro更加简单,概念相对好理解。同时,原有项目对于用户登录态,用户权限的管理都使用到了Shiro,因此选择Shiro作为一个权限框架的学习。Shiro读音为[shee-roh],为日语的“城堡,堡垒”。本文将从两个方面介绍。首先是Shiro的一些设计概念和原理,然后以一个比较简单的Demo为例,介绍基于其实现的登录和权限控制。阅读时长大致45分钟左右。

框架概念和结构介绍

框架

参考:https://shiro.apache.org/architecture.html

简单结构

image.png

完整结构

image.png

核心概念

Subject

表示为当前和软件交互的主体。

SecurityManager

是整个框架的核心,协调多个功能组件一起发挥各自的作用,用于控制所有用户的权限功能。

Realms

realms是将Shiro框架和应用数据连接起来的桥梁,类似数据源。一般情况下,这些数据源存储了用户和权限定义。然后通过不同的realm实现,和Shiro权限框架结合起来。Realms有多种提供的实现,包括JDBC,LDAP,Text(INI)等,当然也可以实现自己的Realm,比如和自有的权限平台连接起来。另外,Realms可以多个组合起来,实现多层次的授权处理。

其他重要概念

Authentication(认证)

用来处理用户的认证过程,即登录过程。主要是通过对用户提供的账号和密码(或凭据)校验,判断是否和保存的凭据匹配,匹配即认证通过,否则是认证失败。

Authorization(授权)

用来处理用户权限的控制,用户权限一般来说使用“角色-权限”的方式,即Role, Permission。不同用户绑定了不同的角色,进而绑定了不同的权限。当然用户也可以直接绑定到权限,但是一般不这么操作。然后权限和应用程序的资源做了绑定,这样实现了用户所属程序资源的控制。这里的资源,一般只某个接口,某个页面,或某个方法。官方的文档提供了如下的几种权限样例。

  1. 角色判断
if ( subject.hasRole(“administrator”) ) {
    //show the ‘Create User’ button
} else {
    //grey-out the button?
} 
  1. 权限判断

注意这里使用A:B:C这种结构,其中的user表示角色,create表示一个操作

if ( subject.isPermitted(“user:create”) ) {
    //show the ‘Create User’ button
} else {
    //grey-out the button?
} 
  1. 资源实例判断
if ( subject.isPermitted(“user:delete:jsmith”) ) {
    //delete the ‘jsmith’ user
} else {
    //don’t delete ‘jsmith’
}

Session Management

Shiro框架提供Session管理,也支持使用数据库等做持久化。容易理解,之前的Subject包括Authentication等概念中,用户的判断其实一定程度是依赖Session的。但是,当我们使用前后端分离的方式时或者某些不需要Session的场景,也可以关闭Shiro的HttpSession功能,更详细的可以参考文后的资料。

Cryptography

这个模块用于一些加密解密和哈希处理,Shiro对相关的算法做了封装,能够比较容易上手使用。

使用样例

代码介绍

代码主体基于Springboot,然后集成Shiro,使用的依赖如下。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.6</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

...

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-starter</artifactId>
    <version>1.9.1</version>
</dependency>

用户凭据和权限定义文件

为了简单起见,这里使用ini文件的方式来定义凭据和权限关系,实际也是一种Realms,是Shiro本身支持的方式,具体的实现逻辑在 org.apache.shiro.realm.text.IniRealm

其中[users]区域,定义用户凭据和角色;[roles]区域定义了角色对应的资源标记。其中“*”通配符可以实现权限的层次控制。如文件中描述,admin角色具有所有资源的权限,而author角色只有文章的创作和保存权限。

#shiro.ini
[users]
user = password, admin
user2 = password2, editor
user3 = password3, author

[roles]
admin = *
editor = articles:*
author = articles:compose,articles:save

接口附加权限的Controller


//authController.java

package com.auth.demo.controller;

import com.auth.demo.entity.AuthUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
@RequestMapping("/auth")
public class AuthController {

    @PostMapping("/login")
    public Object login(@RequestBody AuthUser user) {
        try {
            AuthenticationToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
            SecurityUtils.getSubject().login(token);
            return "login";
        } catch (Exception e) {
            log.error("login failed:{}", user, e);
            throw e;
        }
    }

    @RequiresRoles("admin")
    @GetMapping("/admin/op")
    public Object adminOp() {
        return "adminOp";
    }

    @RequiresPermissions("articles:*")
    @GetMapping("/editor/op")
    public Object editorOp() {
        return "editorOp";
    }

    @RequiresPermissions("articles:compose")
    @GetMapping("/author/compose")
    public Object authorCompose() {
        return "authorCompose";
    }

    @RequiresPermissions("articles:save")
    @GetMapping("/author/save")
    public Object authorSave() {
        return "authorSave";
    }
}

Shiro的相关配置

# used in develop and test
shiro:
  web:
    enabled: true
  loginUrl: /auth/login
  unauthorizedUrl:

登录

通过调用login接口,执行对应的登录操作。登录成功返回对应的数据。

image.png

失败的情况

image.png

权限

用户最小权限

image.png

最小权限用户无中间角色权限

image.png
image.png

相关资料

  1. 官网 https://shiro.apache.org/
  2. https://javawu.com/archives/2164
  3. https://www.baeldung.com/apache-shiro
  4. https://www.cnblogs.com/ckw1988/p/16045695.html
  5. https://www.infoq.com/articles/apache-shiro/
  6. https://blog.csdn.net/xy2953396112/article/details/60867223
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容