一篇搞定!SpringBoot 搭建超安全 Sa-Token 登录鉴权系统

一篇搞定!SpringBoot 搭建超安全 Sa-Token 登录鉴权系统
在现代 Java Web 项目中,登录认证与权限管理是不可或缺的基础功能。传统的框架如 Spring Security 和 Shiro 生态成熟,但初学者和中小项目开发者常常觉得配置繁琐、学习成本高。
Sa-Token 的出现正好填补了这一空白:它是一款轻量级 Java 权限认证框架,既能满足登录认证、权限校验、单点登录(SSO)、OAuth2.0、分布式 Session 和微服务网关鉴权等需求,又极大降低了上手门槛。本文将带你从零开始,在 Spring Boot 环境下快速搭建一个完整的登录鉴权系统,并详细讲解原理和最佳实践。
官网地址:https://sa-token.cc/
Sa-Token 是什么?
Sa-Token 是一个轻量级、功能全面的 Java 权限框架,核心功能包括:
-
登录认证(单账号或多账号体系)
-
权限校验(角色权限、功能权限)
-
单点登录(SSO)
-
OAuth2.0 授权
-
分布式 Session 管理
-
微服务网关鉴权
简单来说,Sa-Token 能解决大多数项目中遇到的权限相关问题,功能齐全且易上手,是国内很多互联网公司正在使用的技术。
为什么选择 Sa-Token?
相比 Shiro、Spring Security,Sa-Token 有几个显著优势:
-
文档友好 官方文档全中文,内容详尽,查阅和理解门槛低。
-
生态稳定 虽然是新晋框架,但在国内开源社区已经形成完整生态,曾多次位列 Gitee 最受欢迎开源项目。
-
极简易用 使用 Sa-Token,仅需几行代码即可实现完整登录鉴权功能,而同样功能使用 Spring Security 可能需要上百行配置。
总结:如果你希望快速搭建安全、功能完善的权限系统,同时避免繁琐配置,Sa-Token 是一个非常理想的选择。
Spring Boot 集成 Sa-Token
引入依赖
以 Spring Boot 2.7.3 为例:
<!-- pom.xml --><dependency><groupId>cn.dev33</groupId><artifactId>sa-token-spring-boot-starter</artifactId><version>1.36.0</version></dependency>
如果是 Spring Boot 3.x,只需将依赖改为:
<artifactId>sa-token-spring-boot3-starter</artifactId>
配置文件(application.yml)
Sa-Token 提供默认配置,可选自定义:
sa-token:token-name: sa-token # Cookie 名称token-style: uuid # Token 风格,可选 uuid|simple-uuid|random-32|random-64|random-128|tik
主启动类示例
package com.icoderoad.satoken;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import cn.dev33.satoken.stp.SaManager;@SpringBootApplicationpublic class SaTokenApplication {public static void main(String[] args) {SpringApplication.run(SaTokenApplication.class, args);// 打印 Sa-Token 配置信息System.out.println(SaManager.getConfig());}}
如果没有自定义配置,SaManager.getConfig() 将打印默认配置。
编写测试 Controller
package com.icoderoad.satoken.controller;import org.springframework.web.bind.annotation.*;import cn.dev33.satoken.stp.StpUtil;@RestController@RequestMapping("/auth")public class AuthController {// 登录接口(测试用,用户名密码写死)@PostMapping("/login")public String doLogin(@RequestParam String username, @RequestParam String password) {if("admin".equals(username) && "123456".equals(password)) {StpUtil.login(10001); // 登录用户,唯一 ID 10001return "登录成功";}return "用户名或密码错误";}// 判断登录状态@GetMapping("/isLogin")public boolean isLogin() {return StpUtil.isLogin();}// 注销@PostMapping("/logout")public String logout() {StpUtil.logout();return "注销成功";}}
原理解析:StpUtil.login() 内部完成了:
-
检查账号是否已登录
-
生成唯一 Token 并创建 Session
-
记录 Token 活跃时间
-
通知全局监听器
-
将 Token 注入 Cookie
浏览器会自动携带 Cookie,后续请求无需手动传递 Token。
权限校验
告诉 Sa-Token 用户权限
实现 StpInterface 接口:
package com.icoderoad.satoken.config;import cn.dev33.satoken.stp.StpInterface;import org.springframework.stereotype.Component;import java.util.List;@Componentpublic class StpInterfaceImpl implements StpInterface {@Overridepublic List<String> getPermissionList(Object loginId, String loginType) {return List.of("user.add","user.update","user.get","user.delete");}@Overridepublic List<String> getRoleList(Object loginId, String loginType) {return List.of("admin","manager");}}
校验权限
@GetMapping("/user/list")public String getUserList() {StpUtil.checkPermission("user-list"); // 如果没有权限,会抛出异常return "用户列表信息";}
添加全局异常处理后,前端报错信息会更友好。
注解鉴权
Sa-Token 提供两种注解鉴权方式:
-
基于拦截器:适合 Controller 层,默认关闭,需要手动注册全局拦截器。
-
基于 AOP:可应用于任意层,侵入性低,注意 AOP 与拦截器不可同时启用。
示例:
@SaCheckPermission("user-add")@PostMapping("/user/add")public String addUser() {return "新增用户成功";}
集成 Redis(分布式环境)
内存存储有两个问题:
-
重启后数据丢失
-
多实例共享困难
解决方案:使用 Redis 作为 Token 存储。
spring:redis:host: localhostport: 6379sa-token:is-read-cookie: trueis-read-header: true
登录后,Sa-Token 会自动将 Token 和 Session 信息写入 Redis,支持集群环境。
前后端分离应用
登录成功后,手动返回 Token 信息:
@PostMapping("/login")public Map<String,Object> login(@RequestParam String username,@RequestParam String password){StpUtil.login(10001);return StpUtil.getTokenInfo();}
前端将 Token 存储在本地,每次请求通过 Header 携带:
Header: tokenName=tokenValue
Sa-Token 自动解析请求头,完成身份验证。
前后端分离场景下 Token 使用
前后端分离时无法依赖 Cookie,需要手动管理 Token:
-
登录成功返回 Token 信息
-
前端存储 Token(localStorage 或 Vue/React 状态管理)
-
请求接口时将 Token 放入 Header
// login.jsasync function login() {const username = document.getElementById("username").value;const password = document.getElementById("password").value;const response = await fetch("/auth/login", {method: "POST",headers: { "Content-Type": "application/x-www-form-urlencoded" },body: `username=${username}&password=${password}`});const data = await response.json();if(data.tokenValue){localStorage.setItem(data.tokenName, data.tokenValue);alert("登录成功");} else {alert(data.msg);}}// 请求接口示例async function getUserList() {const tokenName = "sa-token";const tokenValue = localStorage.getItem(tokenName);const response = await fetch("/auth/user/list", {method: "GET",headers: { [tokenName]: tokenValue }});const text = await response.text();alert(text);}
前端页面(Thymeleaf + Bootstrap 示例)
<!-- templates/login.html --><!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head><meta charset="UTF-8"><title>Sa-Token 登录示例</title><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"></head><body class="bg-light"><div class="container mt-5"><h2 class="mb-4">登录</h2><div class="mb-3"><input type="text" class="form-control" id="username" placeholder="用户名"></div><div class="mb-3"><input type="password" class="form-control" id="password" placeholder="密码"></div><button class="btn btn-primary" onclick="login()">登录</button><button class="btn btn-secondary" onclick="getUserList()">获取用户列表</button></div><script>async function login() {const username = document.getElementById("username").value;const password = document.getElementById("password").value;const params = new URLSearchParams({username, password});const response = await fetch("/auth/login", {method:"POST", body: params});const data = await response.json();if(data.tokenValue){localStorage.setItem(data.tokenName, data.tokenValue);alert("登录成功");} else {alert(data.msg);}}async function getUserList() {const tokenName = "sa-token";const tokenValue = localStorage.getItem(tokenName);const response = await fetch("/auth/user/list", {headers: { [tokenName]: tokenValue }});const text = await response.text();alert(text);}</script></body></html>
总结与扩展
通过本文示例,我们完成了:
-
Spring Boot 项目快速集成 Sa-Token
-
用户登录、注销、状态校验
-
权限与角色管理
-
注解鉴权与 API 鉴权
-
Redis 分布式存储支持
-
前后端分离项目 Token 使用
Sa-Token 还支持记住我、同端互斥、二级认证、账号封禁、单点登录、OAuth2 等功能,接入简单、可扩展性强。相比 Spring Security 和 Shiro,它在国内项目中具有更快的上手体验和灵活性。如果你想快速搭建安全、高效的权限系统,Sa-Token 是一个值得尝试的方案
更多推荐

所有评论(0)