Shiro權(quán)限框架使用和原理分享

背景

目前比較流行的權(quán)限框架有Apache Shiro和 Spring Security。相比Spring Secrity, Shiro更加簡單,概念相對好理解。同時,原有項目對于用戶登錄態(tài),用戶權(quán)限的管理都使用到了Shiro,因此選擇Shiro作為一個權(quán)限框架的學習。Shiro讀音為[shee-roh],為日語的“城堡,堡壘”。本文將從兩個方面介紹。首先是Shiro的一些設(shè)計概念和原理,然后以一個比較簡單的Demo為例,介紹基于其實現(xiàn)的登錄和權(quán)限控制。閱讀時長大致45分鐘左右。

框架概念和結(jié)構(gòu)介紹

框架

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

簡單結(jié)構(gòu)

image.png

完整結(jié)構(gòu)

image.png

核心概念

Subject

表示為當前和軟件交互的主體。

SecurityManager

是整個框架的核心,協(xié)調(diào)多個功能組件一起發(fā)揮各自的作用,用于控制所有用戶的權(quán)限功能。

Realms

realms是將Shiro框架和應(yīng)用數(shù)據(jù)連接起來的橋梁,類似數(shù)據(jù)源。一般情況下,這些數(shù)據(jù)源存儲了用戶和權(quán)限定義。然后通過不同的realm實現(xiàn),和Shiro權(quán)限框架結(jié)合起來。Realms有多種提供的實現(xiàn),包括JDBC,LDAP,Text(INI)等,當然也可以實現(xiàn)自己的Realm,比如和自有的權(quán)限平臺連接起來。另外,Realms可以多個組合起來,實現(xiàn)多層次的授權(quán)處理。

其他重要概念

Authentication(認證)

用來處理用戶的認證過程,即登錄過程。主要是通過對用戶提供的賬號和密碼(或憑據(jù))校驗,判斷是否和保存的憑據(jù)匹配,匹配即認證通過,否則是認證失敗。

Authorization(授權(quán))

用來處理用戶權(quán)限的控制,用戶權(quán)限一般來說使用“角色-權(quán)限”的方式,即Role, Permission。不同用戶綁定了不同的角色,進而綁定了不同的權(quán)限。當然用戶也可以直接綁定到權(quán)限,但是一般不這么操作。然后權(quán)限和應(yīng)用程序的資源做了綁定,這樣實現(xiàn)了用戶所屬程序資源的控制。這里的資源,一般只某個接口,某個頁面,或某個方法。官方的文檔提供了如下的幾種權(quán)限樣例。

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

注意這里使用A:B:C這種結(jié)構(gòu),其中的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管理,也支持使用數(shù)據(jù)庫等做持久化。容易理解,之前的Subject包括Authentication等概念中,用戶的判斷其實一定程度是依賴Session的。但是,當我們使用前后端分離的方式時或者某些不需要Session的場景,也可以關(guān)閉Shiro的HttpSession功能,更詳細的可以參考文后的資料。

Cryptography

這個模塊用于一些加密解密和哈希處理,Shiro對相關(guān)的算法做了封裝,能夠比較容易上手使用。

使用樣例

代碼介紹

代碼主體基于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>

用戶憑據(jù)和權(quán)限定義文件

為了簡單起見,這里使用ini文件的方式來定義憑據(jù)和權(quán)限關(guān)系,實際也是一種Realms,是Shiro本身支持的方式,具體的實現(xiàn)邏輯在 org.apache.shiro.realm.text.IniRealm

其中[users]區(qū)域,定義用戶憑據(jù)和角色;[roles]區(qū)域定義了角色對應(yīng)的資源標記。其中“*”通配符可以實現(xiàn)權(quán)限的層次控制。如文件中描述,admin角色具有所有資源的權(quán)限,而author角色只有文章的創(chuàng)作和保存權(quán)限。

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

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

接口附加權(quán)限的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的相關(guān)配置

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

登錄

通過調(diào)用login接口,執(zhí)行對應(yīng)的登錄操作。登錄成功返回對應(yīng)的數(shù)據(jù)。

image.png

失敗的情況

image.png

權(quán)限

用戶最小權(quán)限

image.png

最小權(quán)限用戶無中間角色權(quán)限

image.png
image.png

相關(guān)資料

  1. 官網(wǎng) 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
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容