SpringBoot集成Sa-Token實(shí)現(xiàn)權(quán)限認(rèn)證流程入門(mén)教程
摘要: 本文介紹SpringBoot集成 Sa-Token 框架的步驟,包括添加依賴、配置文件設(shè)置、注冊(cè)攔截器。還講解了權(quán)限與角色獲取邏輯定義、設(shè)備工具類創(chuàng)建,以及登錄、用戶信息獲取、注銷功能的改造,最后提及用注解實(shí)現(xiàn)鑒權(quán)。

Sa-token 介紹
Sa-Token 是一個(gè)輕量級(jí) Java 權(quán)限認(rèn)證框架,主要解決:登錄認(rèn)證、權(quán)限認(rèn)證、單點(diǎn)登錄、OAuth2.0、分布式Session會(huì)話等一系列權(quán)限相關(guān)問(wèn)題。(本節(jié)僅講解入門(mén)內(nèi)容)
SpringBoot 集成 Sa-Token
1.添加依賴
<!-- Sa-Token 權(quán)限認(rèn)證,在線文檔:https://sa-token.cc -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.44.0</version>
</dependency>注:如果你使用的是 SpringBoot 3.x,只需要將 sa-token-spring-boot-starter 修改為 sa-token-spring-boot3-starter 即可。
2.設(shè)置配置文件
spring:
application:
name: ai-codegen-microservice
sa-token:
# token 名稱(同時(shí)也是 cookie 名稱)
token-name: satoken
# token 有效期(單位:秒) 默認(rèn)30天,-1 代表永久有效
timeout: 2592000
# token 最低活躍頻率,如果 token 超過(guò)此時(shí)間沒(méi)有訪問(wèn)系統(tǒng)就會(huì)被凍結(jié),默認(rèn)-1 代表不限制,永不凍結(jié)
active-timeout: -1
# 是否允許同一賬號(hào)多地同時(shí)登錄 (為 true 時(shí)允許一起登錄, 為 false 時(shí)新登錄擠掉舊登錄)
is-concurrent: true
# 在多人登錄同一賬號(hào)時(shí),是否共用一個(gè) token (為 true 時(shí)所有登錄共用一個(gè) token, 為 false 時(shí)每次登錄新建一個(gè) token)
is-share: false
# token 風(fēng)格(默認(rèn)可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
token-style: uuid
# 是否輸出操作日志
is-log: true3.創(chuàng)建Controller測(cè)試類
/**
* 測(cè)試 Sa-Token 框架實(shí)現(xiàn)用戶登錄
*/
@RestController
@RequestMapping("/test/user/")
public class TestSaTokenLoginController {
// 測(cè)試登錄,瀏覽器訪問(wèn): http://localhost:8101/api/test/user/doLogin?username=zhang&password=123456
@RequestMapping("doLogin")
public String doLogin(String username, String password) {
// 此處僅作模擬示例,真實(shí)項(xiàng)目需要從數(shù)據(jù)庫(kù)中查詢數(shù)據(jù)進(jìn)行比對(duì)
if ("zhang".equals(username) && "123456".equals(password)) {
StpUtil.login(10001);
return "登錄成功";
}
return "登錄失敗";
}
// 查詢登錄狀態(tài),瀏覽器訪問(wèn): http://localhost:8101/api/test/user/isLogin
@RequestMapping("isLogin")
public String isLogin() {
return "當(dāng)前會(huì)話是否登錄:" + StpUtil.isLogin();
}
}然后可以通過(guò)直接訪問(wèn)接口地址來(lái)驗(yàn)證。


后端開(kāi)發(fā)實(shí)現(xiàn)登錄校驗(yàn)與權(quán)限檢驗(yàn)
1.添加依賴并設(shè)置配置文件


2.注冊(cè) Sa-Token 攔截器
新建 satoken 包,在里面新建配置類 SaTokenConfigure,注冊(cè)攔截器:
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
// 注冊(cè) Sa-Token 攔截器,打開(kāi)注解式鑒權(quán)功能
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注冊(cè) Sa-Token 攔截器,打開(kāi)注解式鑒權(quán)功能
registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
}
}然后就可以?使用注解鑒權(quán)了,比?如下列注解,可以平替我們項(xiàng)目中已經(jīng)寫(xiě)的鑒權(quán)注解:
// 登錄校驗(yàn):只有登錄之后才能進(jìn)入該方法
@SaCheckLogin
@RequestMapping("info")
public String info() {
return "查詢用戶信息";
}
// 角色校驗(yàn):必須具有指定角色才能進(jìn)入該方法
@SaCheckRole("super-admin")
@RequestMapping("add")
public String add() {
return "用戶增加";
}3.定義權(quán)限與角色獲取邏輯
部分接口需要特?定的用戶權(quán)限或?qū)?yīng)的角色才能?訪問(wèn),那怎么知道當(dāng)前登錄用戶具有哪些權(quán)限或角色呢?
按照 Sa-Token 的開(kāi)發(fā)模式,我們需要新建一個(gè)類,實(shí)現(xiàn) StpInterface 接口。該接口提供了獲取當(dāng)前登錄用戶的權(quán)限和角色的方法,在每次調(diào)用鑒權(quán)代碼時(shí),都會(huì)執(zhí)行接口中的方法。
在 satoken 包下新建類,代碼如下:
@Component // 保證此類被 SpringBoot 掃描,完成 Sa-Token 的自定義權(quán)限驗(yàn)證擴(kuò)展
public class StpInterfaceImpl implements StpInterface {
/**
* 返回一個(gè)賬號(hào)所擁有的角色標(biāo)識(shí)集合 (權(quán)限與角色可分開(kāi)校驗(yàn))
*/
@Override
public List<String> getRoleList(Object loginId, String s) {
// 從當(dāng)前登錄用戶信息中獲取角色
User user = (User) StpUtil.getSessionByLoginId(loginId).get(USER_LOGIN_STATE);
return Collections.singletonList(user.getUserRole());
}
}4.新建設(shè)備信息獲取工具類
/**
* 設(shè)備工具類
*/
public class DeviceUtils {
/**
* 根據(jù)請(qǐng)求獲取設(shè)備信息
**/
public static String getRequestDevice(HttpServletRequest request) {
String userAgentStr = request.getHeader(Header.USER_AGENT.toString());
// 使用 Hutool 解析 UserAgent
UserAgent userAgent = UserAgentUtil.parse(userAgentStr);
ThrowUtils.throwIf(userAgent == null, ErrorCode.OPERATION_ERROR, "非法請(qǐng)求");
// 默認(rèn)值是 PC
String device = "pc";
// 是否為小程序
if (isMiniProgram(userAgentStr)) {
device = "miniProgram";
} else if (isPad(userAgentStr)) {
// 是否為 Pad
device = "pad";
} else if (userAgent.isMobile()) {
// 是否為手機(jī)
device = "mobile";
}
return device;
}
/**
* 判斷是否是小程序
* 一般通過(guò) User-Agent 字符串中的 "MicroMessenger" 來(lái)判斷是否是微信小程序
**/
private static boolean isMiniProgram(String userAgentStr) {
// 判斷 User-Agent 是否包含 "MicroMessenger" 表示是微信環(huán)境
return StrUtil.containsIgnoreCase(userAgentStr, "MicroMessenger")
&& StrUtil.containsIgnoreCase(userAgentStr, "MiniProgram");
}
/**
* 判斷是否為平板設(shè)備
* 支持 iOS(如 iPad)和 Android 平板的檢測(cè)
**/
private static boolean isPad(String userAgentStr) {
// 檢查 iPad 的 User-Agent 標(biāo)志
boolean isIpad = StrUtil.containsIgnoreCase(userAgentStr, "iPad");
// 檢查 Android 平板(包含 "Android" 且不包含 "Mobile")
boolean isAndroidTablet = StrUtil.containsIgnoreCase(userAgentStr, "Android")
&& !StrUtil.containsIgnoreCase(userAgentStr, "Mobile");
// 如果是 iPad 或 Android 平板,則返回 true
return isIpad || isAndroidTablet;
}
}5.改造登錄接口
修改userLogin 方法中的邏輯,需要給 Sa-Token 設(shè)置登錄態(tài),保存登錄用戶信息。
// Sa-Token 登錄,并指定設(shè)備,同端登錄互斥 StpUtil.login(user.getId(), DeviceUtils.getRequestDevice(request)); StpUtil.getSession().set(USER_LOGIN_STATE, user);
6.改造獲取用戶信息的邏輯
修改getLoginUser ,不再?gòu)?request.getSession() 中獲取登錄用戶的 id,改為從 Sa-Token 中獲取。
@Override
public User getLoginUser(HttpServletRequest request) {
// 先判斷是否已登錄
Object loginUserId = StpUtil.getLoginIdDefaultNull();
if (loginUserId == null) {
throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
}
// 從數(shù)據(jù)庫(kù)查詢(追求性能的話可以注釋,直接走緩存)
User currentUser = this.getById((String) loginUserId);
if (currentUser == null) {
throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
}
return currentUser;
}如果用戶信?息幾乎很少修改,可以?不查數(shù)據(jù)庫(kù),直接從 Sa-Token 的 Session 中獲取之前保存的用戶登錄態(tài):
@Override
public User getLoginUser(HttpServletRequest request) {
// 先判斷是否已登錄
Object loginId = StpUtil.getLoginIdDefaultNull();
if (Objects.isNull(loginId)) {
throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
}
return (User) StpUtil.getSessionByLoginId(loginId).get(USER_LOGIN_STATE);
}7.改造用戶注銷功能
改為調(diào)用 Sa-Token 的注銷方法,移除登錄態(tài):
@Override
public boolean userLogout(HttpServletRequest request) {
StpUtil.checkLogin();
// 移除登錄態(tài)
StpUtil.logout();
return true;
}8. 替換鑒權(quán)注解
如果是管理員權(quán)限的接口,打上以下注解:
@SaCheckRole(UserConstant.ADMIN_ROLE)
到此這篇關(guān)于SpringBoot集成Sa-Token實(shí)現(xiàn)權(quán)限認(rèn)證流程入門(mén)教程的文章就介紹到這了,更多相關(guān)SpringBoot Sa-Token權(quán)限認(rèn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Springboot集成shiro之登錄攔截/權(quán)限控制方式
- SpringBoot整合Spring?Security實(shí)現(xiàn)權(quán)限控制的全過(guò)程
- springboot整合Sa-Token實(shí)現(xiàn)登錄認(rèn)證和權(quán)限校驗(yàn)的詳細(xì)流程
- SpringBoot越權(quán)和數(shù)據(jù)權(quán)限控制的實(shí)現(xiàn)方案(最新整理)
- springboot3整合SpringSecurity實(shí)現(xiàn)登錄校驗(yàn)與權(quán)限認(rèn)證
- SpringBoot?使用?Sa-Token?完成權(quán)限認(rèn)證的操作方法
- SpringBoot整合Springsecurity實(shí)現(xiàn)數(shù)據(jù)庫(kù)登錄及權(quán)限控制功能
- 基于SpringBoot、SpringSecurity、JWT、RBAC搭建一套可落地的權(quán)限系統(tǒng)
相關(guān)文章
Jaxb2實(shí)現(xiàn)JavaBean與xml互轉(zhuǎn)的方法詳解
這篇文章主要介紹了Jaxb2實(shí)現(xiàn)JavaBean與xml互轉(zhuǎn)的方法,簡(jiǎn)單介紹了JAXB的概念、功能及實(shí)現(xiàn)JavaBean與xml互轉(zhuǎn)的具體操作技巧,需要的朋友可以參考下2017-04-04
Java的MyBatis框架中關(guān)鍵的XML字段映射的配置參數(shù)詳解
將XML文件的schema字段映射到數(shù)據(jù)庫(kù)的schema是我們操作數(shù)據(jù)庫(kù)的常用手段,這里我們就來(lái)整理一些Java的MyBatis框架中關(guān)鍵的XML字段映射的配置參數(shù)詳解,需要的朋友可以參考下2016-06-06
springboot獲取訪問(wèn)的ip地址的實(shí)現(xiàn)步驟
本文主要介紹了spring boot獲取訪問(wèn)的ip地址,可以在沒(méi)有HttpServletRequest參數(shù)的情況下獲取IP地址,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-10-10
Spring Boot基礎(chǔ)入門(mén)之基于注解的Mybatis
這篇文章主要給大家介紹了關(guān)于Spring Boot基礎(chǔ)入門(mén)之基于注解的Mybatis的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07
springboot中設(shè)置定時(shí)任務(wù)的三種方法小結(jié)
在我們開(kāi)發(fā)項(xiàng)目過(guò)程中,經(jīng)常需要定時(shí)任務(wù)來(lái)幫助我們來(lái)做一些內(nèi)容,本文介紹了springboot中設(shè)置定時(shí)任務(wù)的三種方法,主要包括@Scheduled注解,Quartz框架和xxl-job框架的實(shí)現(xiàn),感興趣的可以了解一下2023-12-12
Java實(shí)現(xiàn)刪除文件中的指定內(nèi)容
在日常開(kāi)發(fā)中,經(jīng)常需要對(duì)文本文件進(jìn)行批量處理,其中,刪除文件中指定內(nèi)容是最常見(jiàn)的需求之一,下面我們就來(lái)看看如何使用java實(shí)現(xiàn)刪除文件中的指定內(nèi)容吧2025-06-06

