日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
再見,Shiro!你好,Sa-Token!

Sa-Token 介紹

Sa-Token 是一個輕量級 Java 權(quán)限認證框架,主要解決:登錄認證、權(quán)限認證、單點登錄、OAuth2.0、分布式Session會話、微服務網(wǎng)關(guān)鑒權(quán) 等一系列權(quán)限相關(guān)問題。

堅守“ 做人真誠 · 做事靠譜 · 口碑至上 · 高效敬業(yè) ”的價值觀,專業(yè)網(wǎng)站建設服務10余年為成都成都生料攪拌車小微創(chuàng)業(yè)公司專業(yè)提供企業(yè)網(wǎng)站建設營銷網(wǎng)站建設商城網(wǎng)站建設手機網(wǎng)站建設小程序網(wǎng)站建設網(wǎng)站改版,從內(nèi)容策劃、視覺設計、底層架構(gòu)、網(wǎng)頁布局、功能開發(fā)迭代于一體的高端網(wǎng)站建設服務。

Sa-Token 旨在以簡單、優(yōu)雅的方式完成系統(tǒng)的權(quán)限認證部分,以登錄認證為例,你只需要:

// 會話登錄,參數(shù)填登錄人的賬號id 
StpUtil.login(10001);

無需實現(xiàn)任何接口,無需創(chuàng)建任何配置文件,只需要這一句靜態(tài)代碼的調(diào)用,便可以完成會話登錄認證。

如果一個接口需要登錄后才能訪問,我們只需調(diào)用以下代碼:

// 校驗當前客戶端是否已經(jīng)登錄,如果未登錄則拋出 `NotLoginException` 異常
StpUtil.checkLogin();

在 Sa-Token 中,大多數(shù)功能都可以一行代碼解決:

踢人下線:

// 將賬號id為 10077 的會話踢下線 
StpUtil.kickout(10077);

權(quán)限認證:

// 注解鑒權(quán):只有具備 `user:add` 權(quán)限的會話才可以進入方法
@SaCheckPermission("user:add")
    public String insert(SysUser user) {
    // ... 
    return "用戶增加";
}

路由攔截鑒權(quán):

// 根據(jù)路由劃分模塊,不同模塊不同鑒權(quán) 
registry.addInterceptor(new SaInterceptor(handler -> {
    SaRouter.match("/user/**", r -> StpUtil.checkPermission("user"));
    SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin"));
    SaRouter.match("/goods/**", r -> StpUtil.checkPermission("goods"));
    SaRouter.match("/orders/**", r -> StpUtil.checkPermission("orders"));
    SaRouter.match("/notice/**", r -> StpUtil.checkPermission("notice"));
    // 更多模塊... 
})).addPathPatterns("/**");

當你受夠 Shiro、SpringSecurity 等框架的三拜九叩之后,你就會明白,相對于這些傳統(tǒng)老牌框架,Sa-Token 的 API 設計是多么的簡單、優(yōu)雅!

Sa-Token 功能一覽

Sa-Token 目前主要五大功能模塊:登錄認證、權(quán)限認證、單點登錄、OAuth2.0、微服務鑒權(quán)。

  • 登錄認證 —— 單端登錄、多端登錄、同端互斥登錄、七天內(nèi)免登錄
  • 權(quán)限認證 —— 權(quán)限認證、角色認證、會話二級認證
  • Session會話 —— 全端共享Session、單端獨享Session、自定義Session
  • 踢人下線 —— 根據(jù)賬號id踢人下線、根據(jù)Token值踢人下線
  • 賬號封禁 —— 登錄封禁、按照業(yè)務分類封禁、按照處罰階梯封禁
  • 持久層擴展 —— 可集成Redis、Memcached等專業(yè)緩存中間件,重啟數(shù)據(jù)不丟失
  • 分布式會話 —— 提供jwt集成、共享數(shù)據(jù)中心兩種分布式會話方案
  • 微服務網(wǎng)關(guān)鑒權(quán) —— 適配Gateway、ShenYu、Zuul等常見網(wǎng)關(guān)的路由攔截認證
  • 單點登錄 —— 內(nèi)置三種單點登錄模式:無論是否跨域、是否共享Redis,都可以搞定
  • OAuth2.0認證 —— 輕松搭建 OAuth2.0 服務,支持openid模式
  • 二級認證 —— 在已登錄的基礎(chǔ)上再次認證,保證安全性
  • Basic認證 —— 一行代碼接入 Http Basic 認證
  • 獨立Redis —— 將權(quán)限緩存與業(yè)務緩存分離
  • 臨時Token認證 —— 解決短時間的Token授權(quán)問題
  • 模擬他人賬號 —— 實時操作任意用戶狀態(tài)數(shù)據(jù)
  • 臨時身份切換 —— 將會話身份臨時切換為其它賬號
  • 前后臺分離 —— APP、小程序等不支持Cookie的終端
  • 同端互斥登錄 —— 像QQ一樣手機電腦同時在線,但是兩個手機上互斥登錄
  • 多賬號認證體系 —— 比如一個商城項目的user表和admin表分開鑒權(quán)
  • Token風格定制 —— 內(nèi)置六種Token風格,還可:自定義Token生成策略、自定義Token前綴
  • 注解式鑒權(quán) —— 優(yōu)雅的將鑒權(quán)與業(yè)務代碼分離
  • 路由攔截式鑒權(quán) —— 根據(jù)路由攔截鑒權(quán),可適配restful模式
  • 自動續(xù)簽 —— 提供兩種Token過期策略,靈活搭配使用,還可自動續(xù)簽
  • 會話治理 —— 提供方便靈活的會話查詢接口
  • 記住我模式 —— 適配[記住我]模式,重啟瀏覽器免驗證
  • 密碼加密 —— 提供密碼加密模塊,可快速MD5、SHA1、SHA256、AES、RSA加密
  • 全局偵聽器 —— 在用戶登陸、注銷、被踢下線等關(guān)鍵性操作時進行一些AOP操作
  • 開箱即用 —— 提供SpringMVC、WebFlux等常見web框架starter集成包,真正的開箱即用

SpringBoot 集成 Sa-Token

一、添加maven依賴



  cn.dev33
  sa-token-spring-boot-starter
  1.34.0

注:如果你使用的 SpringBoot 3.x,只需要將 sa-token-spring-boot-starter 修改為 sa-token-spring-boot3-starter 即可。

二、設置配置文件

你可以零配置啟動項目 ,但同時你也可以在 application.yml 中增加如下配置,定制性使用框架:

server:
    # 端口
    port: 8081


############## Sa-Token 配置 (文檔: https://sa-token.cc) ##############
sa-token: 
    # token名稱 (同時也是cookie名稱)
    token-name: satoken
    # token有效期,單位s 默認30天, -1代表永不過期 
    timeout: 2592000
    # token臨時有效期 (指定時間內(nèi)無操作就視為token過期) 單位: 秒
    activity-timeout: -1
    # 是否允許同一賬號并發(fā)登錄 (為true時允許一起登錄, 為false時新登錄擠掉舊登錄) 
    is-concurrent: true
    # 在多人登錄同一賬號時,是否共用一個token (為true時所有登錄共用一個token, 為false時每次登錄新建一個token) 
    is-share: true
    # token風格
    token-style: uuid
    # 是否輸出操作日志 
    is-log: false

三、創(chuàng)建案例

@RestController
    @RequestMapping("/user/")
    public class UserController {


        // 測試登錄,瀏覽器訪問:http://localhost:8081/user/doLogin?username=zhang&password=123456
        @RequestMapping("doLogin")
        public String doLogin(String username, String password) {
            // 此處僅作模擬示例,真實項目需要從數(shù)據(jù)庫中查詢數(shù)據(jù)進行比對 
            if("iron".equals(username) && "123456".equals(password)) {
                StpUtil.login(10001);
                return "登錄成功";
            }
            return "登錄失敗";
        }


        // 查詢登錄狀態(tài),瀏覽器訪問:http://localhost:8081/user/isLogin
        @RequestMapping("isLogin")
        public String isLogin() {
            return "當前會話是否登錄:" + StpUtil.isLogin();
        }


    }

登錄認證

設計思路

對于一些登錄之后才能訪問的接口(例如:查詢我的賬號資料),我們通常的做法是增加一層接口校驗:

  • 如果校驗通過,則:正常返回數(shù)據(jù)。
  • 如果校驗未通過,則:拋出異常,告知其需要先進行登錄。

那么,判斷會話是否登錄的依據(jù)是什么?我們先來簡單分析一下登錄訪問流程:

  1. 用戶提交 name + password 參數(shù),調(diào)用登錄接口。
  2. 登錄成功,返回這個用戶的 Token 會話憑證。
  3. 用戶后續(xù)的每次請求,都攜帶上這個 Token。
  4. 服務器根據(jù) Token 判斷此會話是否登錄成功。

所謂登錄認證,指的就是服務器校驗賬號密碼,為用戶頒發(fā) Token 會話憑證的過程,這個 Token 也是我們后續(xù)判斷會話是否登錄的關(guān)鍵所在。

登錄與注銷

根據(jù)以上思路,我們需要一個會話登錄的函數(shù):

// 會話登錄:參數(shù)填寫要登錄的賬號id,建議的數(shù)據(jù)類型:long | int | String, 不可以傳入復雜類型,如:User、Admin 等等
StpUtil.login(Object id);

只此一句代碼,便可以使會話登錄成功,實際上,Sa-Token 在背后做了大量的工作,包括但不限于:

  1. 檢查此賬號是否之前已有登錄
  2. 為賬號生成 Token 憑證與 Session 會話
  3. 通知全局偵聽器,xx 賬號登錄成功
  4. 將 Token 注入到請求上下文
  5. 等等其它工作……

你暫時不需要完整的了解整個登錄過程,你只需要記住關(guān)鍵一點:Sa-Token 為這個賬號創(chuàng)建了一個Token憑證,且通過 Cookie 上下文返回給了前端。

所以一般情況下,我們的登錄接口代碼,會大致類似如下:

// 會話登錄接口 
@RequestMapping("doLogin")
    public SaResult doLogin(String name, String pwd) {
    // 第一步:比對前端提交的賬號名稱、密碼
    if("iron".equals(name) && "123456".equals(pwd)) {
        // 第二步:根據(jù)賬號id,進行登錄 
        StpUtil.login(10001);
        return SaResult.ok("登錄成功");
    }
    return SaResult.error("登錄失敗");
}

如果你對以上代碼閱讀沒有壓力,你可能會注意到略顯奇怪的一點:此處僅僅做了會話登錄,但并沒有主動向前端返回 Token 信息。是因為不需要嗎?嚴格來講是需要的,只不過 StpUtil.login(id) 方法利用了 Cookie 自動注入的特性,省略了你手寫返回 Token 的代碼。

如果你對 Cookie 功能還不太了解,也不用擔心,我們會在之后的 [ 前后端分離 ] 章節(jié)中詳細的闡述 Cookie 功能,現(xiàn)在你只需要了解最基本的兩點:

  • Cookie 可以從后端控制往瀏覽器中寫入 Token 值。
  • Cookie 會在前端每次發(fā)起請求時自動提交 Token 值。

因此,在 Cookie 功能的加持下,我們可以僅靠 StpUtil.login(id) 一句代碼就完成登錄認證。

除了登錄方法,我們還需要:

// 當前會話注銷登錄
StpUtil.logout();


// 獲取當前會話是否已經(jīng)登錄,返回true=已登錄,false=未登錄
StpUtil.isLogin();


// 檢驗當前會話是否已經(jīng)登錄, 如果未登錄,則拋出異常:`NotLoginException`
StpUtil.checkLogin();

異常 NotLoginException 代表當前會話暫未登錄,可能的原因有很多:前端沒有提交 Token、前端提交的 Token 是無效的、前端提交的 Token 已經(jīng)過期 …… 等等,可參照此篇:未登錄場景值,了解如何獲取未登錄的場景值。

會話查詢

// 獲取當前會話賬號id, 如果未登錄,則拋出異常:`NotLoginException`
StpUtil.getLoginId();


// 類似查詢API還有:
StpUtil.getLoginIdAsString();    // 獲取當前會話賬號id, 并轉(zhuǎn)化為`String`類型
StpUtil.getLoginIdAsInt();       // 獲取當前會話賬號id, 并轉(zhuǎn)化為`int`類型
StpUtil.getLoginIdAsLong();      // 獲取當前會話賬號id, 并轉(zhuǎn)化為`long`類型


// ---------- 指定未登錄情形下返回的默認值 ----------


// 獲取當前會話賬號id, 如果未登錄,則返回null 
StpUtil.getLoginIdDefaultNull();


// 獲取當前會話賬號id, 如果未登錄,則返回默認值 (`defaultValue`可以為任意類型)
StpUtil.getLoginId(T defaultValue);

Token 查詢

// 獲取當前會話的token值
StpUtil.getTokenValue();


// 獲取當前`StpLogic`的token名稱
StpUtil.getTokenName();


// 獲取指定token對應的賬號id,如果未登錄,則返回 null
StpUtil.getLoginIdByToken(String tokenValue);


// 獲取當前會話剩余有效期(單位:s,返回-1代表永久有效)
StpUtil.getTokenTimeout();


// 獲取當前會話的token信息參數(shù)
StpUtil.getTokenInfo();

有關(guān)TokenInfo參數(shù)詳解,請參考:TokenInfo參數(shù)詳解

來個小測試,加深一下理解

新建 LoginController,復制以下代碼

/**
 * 登錄測試 
 */
@RestController
@RequestMapping("/acc/")
public class LoginController {


    // 測試登錄  ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456
    @RequestMapping("doLogin")
    public SaResult doLogin(String name, String pwd) {
        // 此處僅作模擬示例,真實項目需要從數(shù)據(jù)庫中查詢數(shù)據(jù)進行比對 
        if("iron".equals(name) && "123456".equals(pwd)) {
            StpUtil.login(10001);
            return SaResult.ok("登錄成功");
        }
        return SaResult.error("登錄失敗");
    }


    // 查詢登錄狀態(tài)  ---- http://localhost:8081/acc/isLogin
    @RequestMapping("isLogin")
    public SaResult isLogin() {
        return SaResult.ok("是否登錄:" + StpUtil.isLogin());
    }


    // 查詢 Token 信息  ---- http://localhost:8081/acc/tokenInfo
    @RequestMapping("tokenInfo")
    public SaResult tokenInfo() {
        return SaResult.data(StpUtil.getTokenInfo());
    }


    // 測試注銷  ---- http://localhost:8081/acc/logout
    @RequestMapping("logout")
    public SaResult logout() {
        StpUtil.logout();
        return SaResult.ok();
    }


}

權(quán)限認證

設計思路

所謂權(quán)限認證,核心邏輯就是判斷一個賬號是否擁有指定權(quán)限:

  • 有,就讓你通過。
  • 沒有?那么禁止訪問!

深入到底層數(shù)據(jù)中,就是每個賬號都會擁有一個權(quán)限碼集合,框架來校驗這個集合中是否包含指定的權(quán)限碼。

例如:當前賬號擁有權(quán)限碼集合 ["user-add", "user-delete", "user-get"],這時候我來校驗權(quán)限 "user-update",則其結(jié)果就是:驗證失敗,禁止訪問。

所以現(xiàn)在問題的核心就是:

  1. 如何獲取一個賬號所擁有的的權(quán)限碼集合?
  2. 本次操作需要驗證的權(quán)限碼是哪個?

獲取當前賬號權(quán)限碼集合

因為每個項目的需求不同,其權(quán)限設計也千變?nèi)f化,因此 [ 獲取當前賬號權(quán)限碼集合 ] 這一操作不可能內(nèi)置到框架中, 所以 Sa-Token 將此操作以接口的方式暴露給你,以方便你根據(jù)自己的業(yè)務邏輯進行重寫。

你需要做的就是新建一個類,實現(xiàn) StpInterface接口,例如以下代碼:

/**
 * 自定義權(quán)限驗證接口擴展
 */
@Component    // 保證此類被SpringBoot掃描,完成Sa-Token的自定義權(quán)限驗證擴展 
public class StpInterfaceImpl implements StpInterface {


    /**
     * 返回一個賬號所擁有的權(quán)限碼集合 
     */
    @Override
    public List getPermissionList(Object loginId, String loginType) {
        // 本list僅做模擬,實際項目中要根據(jù)具體業(yè)務邏輯來查詢權(quán)限
        List list = new ArrayList();    
        list.add("101");
        list.add("user.add");
        list.add("user.update");
        list.add("user.get");
        // list.add("user.delete");
        list.add("art.*");
        return list;
    }


    /**
     * 返回一個賬號所擁有的角色標識集合 (權(quán)限與角色可分開校驗)
     */
    @Override
    public List getRoleList(Object loginId, String loginType) {
        // 本list僅做模擬,實際項目中要根據(jù)具體業(yè)務邏輯來查詢角色
        List list = new ArrayList();    
        list.add("admin");
        list.add("super-admin");
        return list;
    }


}

參數(shù)解釋:

  • loginId:賬號id,即你在調(diào)用 StpUtil.login(id) 時寫入的標識值。
  • loginType:賬號體系標識,此處可以暫時忽略,在 [ 多賬戶認證 ] 章節(jié)下會對這個概念做詳細的解釋。

可參考代碼:碼云:StpInterfaceImpl.java

注意: StpInterface 接口在需要鑒權(quán)時由框架自動調(diào)用,開發(fā)者只需要配置好就可以使用下面的鑒權(quán)方法或后面的注解鑒權(quán)

權(quán)限校驗

然后就可以用以下api來鑒權(quán)了

// 獲?。寒斍百~號所擁有的權(quán)限集合
StpUtil.getPermissionList();


// 判斷:當前賬號是否含有指定權(quán)限, 返回 true 或 false
StpUtil.hasPermission("user.add");        


// 校驗:當前賬號是否含有指定權(quán)限, 如果驗證未通過,則拋出異常: NotPermissionException 
StpUtil.checkPermission("user.add");        


// 校驗:當前賬號是否含有指定權(quán)限 [指定多個,必須全部驗證通過]
StpUtil.checkPermissionAnd("user.add", "user.delete", "user.get");        


// 校驗:當前賬號是否含有指定權(quán)限 [指定多個,只要其一驗證通過即可]
StpUtil.checkPermissionOr("user.add", "user.delete", "user.get");

擴展:NotPermissionException 對象可通過 getLoginType() 方法獲取具體是哪個 StpLogic 拋出的異常

角色校驗

在Sa-Token中,角色和權(quán)限可以獨立驗證

// 獲?。寒斍百~號所擁有的角色集合
StpUtil.getRoleList();


// 判斷:當前賬號是否擁有指定角色, 返回 true 或 false
StpUtil.hasRole("super-admin");        


// 校驗:當前賬號是否含有指定角色標識, 如果驗證未通過,則拋出異常: NotRoleException
StpUtil.checkRole("super-admin");        


// 校驗:當前賬號是否含有指定角色標識 [指定多個,必須全部驗證通過]
StpUtil.checkRoleAnd("super-admin", "shop-admin");        


// 校驗:當前賬號是否含有指定角色標識 [指定多個,只要其一驗證通過即可] 
StpUtil.checkRoleOr("super-admin", "shop-admin");

擴展:NotRoleException 對象可通過 getLoginType() 方法獲取具體是哪個 StpLogic 拋出的異常

權(quán)限通配符

Sa-Token允許你根據(jù)通配符指定泛權(quán)限,例如當一個賬號擁有art.*的權(quán)限時,art.add、art.delete、art.update都將匹配通過

// 當擁有 art.* 權(quán)限時
StpUtil.hasPermission("art.add");        // true
StpUtil.hasPermission("art.update");     // true
StpUtil.hasPermission("goods.add");      // false


// 當擁有 *.delete 權(quán)限時
StpUtil.hasPermission("art.delete");      // true
StpUtil.hasPermission("user.delete");     // true
StpUtil.hasPermission("user.update");     // false


// 當擁有 *.js 權(quán)限時
StpUtil.hasPermission("index.js");        // true
StpUtil.hasPermission("index.css");       // false
StpUtil.hasPermission("index.html");      // false

上帝權(quán)限:當一個賬號擁有 "*" 權(quán)限時,他可以驗證通過任何權(quán)限碼 (角色認證同理)

如何把權(quán)限精確到按鈕級?

權(quán)限精確到按鈕級的意思就是指:權(quán)限范圍可以控制到頁面上的每一個按鈕是否顯示。

思路:如此精確的范圍控制只依賴后端已經(jīng)難以完成,此時需要前端進行一定的邏輯判斷。

如果是前后端一體項目,可以參考:Thymeleaf 標簽方言,如果是前后端分離項目,則:

  1. 在登錄時,把當前賬號擁有的所有權(quán)限碼一次性返回給前端。
  2. 前端將權(quán)限碼集合保存在localStorage或其它全局狀態(tài)管理對象中。
  3. 在需要權(quán)限控制的按鈕上,使用 js 進行邏輯判斷,例如在Vue框架中我們可以使用如下寫法:

其中:arr是當前用戶擁有的權(quán)限碼數(shù)組,user.delete是顯示按鈕需要擁有


本文名稱:再見,Shiro!你好,Sa-Token!
瀏覽地址:http://www.dlmjj.cn/article/djeossd.html