mirror of
https://github.com/click33/sa-token-go.git
synced 2026-04-22 23:37:07 +08:00
04a9e5a72f
2、完善部分功能
21 KiB
21 KiB
Sa-Token-Go
中文文档 | English
一个轻量级、高性能的 Go 权限认证框架,参考 sa-token 设计。
✨ 核心特性
- 🔐 登录认证 - 支持多设备登录、Token管理
- 🛡️ 权限验证 - 细粒度权限控制、通配符支持(
*,user:*,user:*:view) - 👥 角色管理 - 灵活的角色授权机制
- 🚫 账号封禁 - 临时/永久封禁功能
- 👢 踢人下线 - 强制用户下线、多端互斥登录
- 💾 Session会话 - 完整的Session管理
- ⏰ 活跃检测 - 自动检测Token活跃度
- 🔄 自动续期 - Token异步自动续期(性能提升400%)
- 🎨 注解支持 -
@SaCheckLogin、@SaCheckRole、@SaCheckPermission - 🎧 事件监听 - 强大的事件系统、支持优先级、异步执行
- 📦 模块化设计 - 按需导入、最小依赖
- 🔒 Nonce防重放 - 防止请求重放攻击、一次性令牌
- 🔄 Refresh Token - 刷新令牌机制、无感刷新
- 🔐 OAuth2 - 完整的OAuth2授权码模式实现
🎨 Token 风格
Sa-Token-Go 支持 9 种 Token 生成风格:
| 风格 | 格式示例 | 长度 | 适用场景 |
|---|---|---|---|
| UUID | 550e8400-e29b-41d4-... |
36 | 通用场景 |
| Simple | aB3dE5fG7hI9jK1l |
16 | 紧凑型Token |
| Random32/64/128 | 随机字符串 | 32/64/128 | 高安全性 |
| JWT | eyJhbGciOiJIUzI1... |
可变 | 无状态认证 |
| Hash 🆕 | a3f5d8b2c1e4f6a9... |
64 | SHA256哈希 |
| Timestamp 🆕 | 1700000000123_user1000_... |
可变 | 可追溯时间 |
| Tik 🆕 | 7Kx9mN2pQr4 |
11 | 短ID(类似抖音) |
🔒 安全特性
Nonce 防重放攻击
// 生成nonce
nonce, _ := stputil.GenerateNonce()
// 验证nonce(一次性使用)
valid := stputil.VerifyNonce(nonce) // true
valid = stputil.VerifyNonce(nonce) // false(防止重放)
Refresh Token 刷新机制
// 登录获取访问令牌和刷新令牌
tokenInfo, _ := stputil.LoginWithRefreshToken(1000, "web")
fmt.Println("Access Token:", tokenInfo.AccessToken)
fmt.Println("Refresh Token:", tokenInfo.RefreshToken)
// 刷新访问令牌
newInfo, _ := stputil.RefreshAccessToken(tokenInfo.RefreshToken)
OAuth2 授权码模式
// 创建OAuth2服务器
oauth2Server := stputil.GetOAuth2Server()
// 注册客户端
oauth2Server.RegisterClient(&core.OAuth2Client{
ClientID: "webapp",
ClientSecret: "secret123",
RedirectURIs: []string{"http://localhost:8080/callback"},
GrantTypes: []core.OAuth2GrantType{core.GrantTypeAuthorizationCode},
Scopes: []string{"read", "write"},
})
// 生成授权码
authCode, _ := oauth2Server.GenerateAuthorizationCode(
"webapp", "http://localhost:8080/callback", "user123", []string{"read"},
)
// 用授权码换取访问令牌
accessToken, _ := oauth2Server.ExchangeCodeForToken(
authCode.Code, "webapp", "secret123", "http://localhost:8080/callback",
)
🚀 快速开始
安装
方式一:简化导入(推荐)✨
只需导入一个框架集成包,自动包含 core 和 stputil 功能!
# 只导入框架集成包(自动包含 core + stputil)
go get github.com/click33/sa-token-go/integrations/gin@v0.1.0 # Gin框架
# 或
go get github.com/click33/sa-token-go/integrations/echo@v0.1.0 # Echo框架
# 或
go get github.com/click33/sa-token-go/integrations/fiber@v0.1.0 # Fiber框架
# 或
go get github.com/click33/sa-token-go/integrations/chi@v0.1.0 # Chi框架
# 存储模块(选一个)
go get github.com/click33/sa-token-go/storage/memory@v0.1.0 # 内存存储(开发)
go get github.com/click33/sa-token-go/storage/redis@v0.1.0 # Redis存储(生产)
方式二:分开导入
# 核心模块
go get github.com/click33/sa-token-go/core@v0.1.0
go get github.com/click33/sa-token-go/stputil@v0.1.0
# 存储模块(选一个)
go get github.com/click33/sa-token-go/storage/memory@v0.1.0 # 内存存储(开发)
go get github.com/click33/sa-token-go/storage/redis@v0.1.0 # Redis存储(生产)
# 框架集成(可选)
go get github.com/click33/sa-token-go/integrations/gin@v0.1.0 # Gin框架
go get github.com/click33/sa-token-go/integrations/echo@v0.1.0 # Echo框架
go get github.com/click33/sa-token-go/integrations/fiber@v0.1.0 # Fiber框架
go get github.com/click33/sa-token-go/integrations/chi@v0.1.0 # Chi框架
超简洁使用(一行初始化)
package main
import (
"github.com/click33/sa-token-go/core"
"github.com/click33/sa-token-go/stputil"
"github.com/click33/sa-token-go/storage/memory"
)
func init() {
// 🎯 一行初始化!显示启动 Banner
stputil.SetManager(
core.NewBuilder().
Storage(memory.NewStorage()).
TokenName("Authorization").
Timeout(86400). // 24小时
TokenStyle(core.TokenStyleRandom64). // Token风格
IsPrintBanner(true). // 显示启动Banner
Build(),
)
}
启动时会显示 Banner:
_____ ______ __ ______
/ ___/____ _ /_ __/___ / /_____ ____ / ____/____
\__ \/ __ | / / / __ \/ //_/ _ \/ __ \_____/ / __/ __ \
___/ / /_/ / / / / /_/ / ,< / __/ / / /_____/ /_/ / /_/ /
/____/\__,_/ /_/ \____/_/|_|\___/_/ /_/ \____/\____/
:: Sa-Token-Go :: (v0.1.0)
:: Go Version :: go1.21.0
:: GOOS/GOARCH :: darwin/arm64
┌─────────────────────────────────────────────────────────┐
│ Token Style : random64 │
│ Token Timeout : 86400 seconds │
│ Auto Renew : true │
└─────────────────────────────────────────────────────────┘
func main() { // 🚀 直接使用 StpUtil,无需传递manager token, _ := stputil.Login(1000) println("登录成功,Token:", token)
// 设置权限
stputil.SetPermissions(1000, []string{"user:read", "user:write"})
// 检查权限
if stputil.HasPermission(1000, "user:read") {
println("有权限!")
}
// 登出
stputil.Logout(1000)
}
### Gin框架集成(单一导入)✨
**新方式:只导入 `integrations/gin` 即可使用所有功能!**
```go
import (
"github.com/gin-gonic/gin"
sagin "github.com/click33/sa-token-go/integrations/gin" // 只需这一个导入!
"github.com/click33/sa-token-go/storage/memory"
)
func main() {
// 初始化(所有功能都在 sagin 包中)
storage := memory.NewStorage()
config := sagin.DefaultConfig() // 使用 sagin.DefaultConfig
manager := sagin.NewManager(storage, config) // 使用 sagin.NewManager
sagin.SetManager(manager) // 使用 sagin.SetManager
r := gin.Default()
// 登录接口
r.POST("/login", func(c *gin.Context) {
userID := c.PostForm("user_id")
token, _ := sagin.Login(userID) // 使用 sagin.Login
c.JSON(200, gin.H{"token": token})
})
// 使用注解装饰器(类似Java)
r.GET("/public", sagin.Ignore(), publicHandler) // 公开访问
r.GET("/user", sagin.CheckLogin(), userHandler) // 需要登录
r.GET("/admin", sagin.CheckPermission("admin:*"), adminHandler) // 需要权限
r.GET("/manager", sagin.CheckRole("manager"), managerHandler) // 需要角色
r.GET("/sensitive", sagin.CheckDisable(), sensitiveHandler) // 检查封禁
r.Run(":8080")
}
📦 项目结构
sa-token-go/
├── core/ # 🔴 核心模块(必需)
│ ├── adapter/ # 适配器接口
│ │ ├── storage.go # 存储接口
│ │ └── context.go # 请求上下文接口
│ ├── manager/ # 认证管理器
│ ├── builder/ # Builder构建器
│ ├── session/ # Session管理
│ ├── token/ # Token生成器(支持JWT)
│ ├── listener/ # 事件监听系统
│ ├── banner/ # 启动Banner
│ ├── config/ # 配置定义
│ ├── context/ # Sa-Token上下文
│ ├── utils/ # 工具函数
│ ├── errors.go # 错误定义
│ └── satoken.go # 核心导出
│
├── stputil/ # 🔧 全局工具类(推荐)
│ └── stputil.go # StpUtil.Login(), StpUtil.Logout()...
│
├── storage/ # 💾 存储后端
│ ├── memory/ # 内存存储(开发环境)
│ │ └── memory.go
│ └── redis/ # Redis存储(生产环境)
│ └── redis.go
│
├── integrations/ # 🌐 框架集成
│ ├── gin/ # Gin框架(包含注解)
│ │ ├── context.go
│ │ ├── plugin.go
│ │ └── annotation.go
│ ├── echo/ # Echo框架
│ │ ├── context.go
│ │ └── plugin.go
│ ├── fiber/ # Fiber框架
│ │ ├── context.go
│ │ └── plugin.go
│ └── chi/ # Chi框架
│ ├── context.go
│ └── plugin.go
│
├── examples/ # 📚 示例项目
│ ├── quick-start/
│ │ └── simple-example/ # ⚡ 快速开始
│ ├── annotation/
│ │ └── annotation-example/ # 🎨 注解使用
│ ├── jwt-example/ # 🔑 JWT Token示例
│ ├── redis-example/ # 💾 Redis存储示例
│ ├── listener-example/ # 🎧 事件监听示例
│ ├── gin/gin-example/ # Gin集成示例
│ ├── echo/echo-example/ # Echo集成示例
│ ├── fiber/fiber-example/ # Fiber集成示例
│ └── chi/chi-example/ # Chi集成示例
│
├── docs/ # 📖 文档
│ ├── tutorial/ # 教程
│ │ └── quick-start.md
│ ├── guide/ # 指南
│ │ ├── authentication.md
│ │ ├── permission.md
│ │ ├── annotation.md
│ │ ├── listener.md
│ │ ├── jwt.md
│ │ ├── redis-storage.md # 英文
│ │ └── redis-storage_zh.md # 中文
│ ├── api/ # API文档
│ └── design/ # 设计文档
│
├── go.work # Go工作区
├── README.md # 英文README
└── README_zh.md # 中文README
🎧 事件监听
监听认证和授权事件,实现审计日志、安全监控等功能:
// 创建事件管理器
eventMgr := core.NewEventManager()
// 监听登录事件
eventMgr.RegisterFunc(core.EventLogin, func(data *core.EventData) {
fmt.Printf("[LOGIN] User: %s, Token: %s\n", data.LoginID, data.Token)
// 记录审计日志、发送通知等
})
// 监听注销事件
eventMgr.RegisterFunc(core.EventLogout, func(data *core.EventData) {
fmt.Printf("[LOGOUT] User: %s\n", data.LoginID)
})
// 高级特性:优先级、同步执行
eventMgr.RegisterWithConfig(core.EventLogin,
core.ListenerFunc(auditLogger),
core.ListenerConfig{
Priority: 100, // 高优先级
Async: false, // 同步执行
},
)
// 监听所有事件(通配符)
eventMgr.RegisterFunc(core.EventAll, func(data *core.EventData) {
log.Printf("[%s] %s", data.Event, data.LoginID)
})
可用事件:
EventLogin- 用户登录EventLogout- 用户登出EventKickout- 强制下线EventDisable- 账号封禁EventPermissionCheck- 权限检查EventRoleCheck- 角色检查EventAll- 所有事件(通配符)
📖 项目结构
sa-token-go/
├── core/ # 核心模块
│ ├── adapter/ # 适配器接口
│ ├── builder/ # Builder构建器
│ ├── config/ # 配置
│ ├── context/ # 上下文
│ ├── listener/ # 事件监听
│ ├── manager/ # 认证管理器
│ ├── oauth2/ # OAuth2实现 🆕
│ ├── security/ # 安全特性(Nonce、RefreshToken)🆕
│ ├── session/ # Session管理
│ ├── token/ # Token生成器
│ └── utils/ # 工具函数
│
├── stputil/ # 全局工具类
│
├── storage/ # 存储模块
│ ├── memory/ # 内存存储
│ └── redis/ # Redis存储
│
├── integrations/ # 框架集成
│ ├── gin/ # Gin集成(含注解)
│ ├── echo/ # Echo集成
│ ├── fiber/ # Fiber集成
│ └── chi/ # Chi集成
│
├── examples/ # 示例项目
│ ├── quick-start/ # 快速开始
│ ├── token-styles/ # Token风格演示 🆕
│ ├── security-features/ # 安全特性演示 🆕
│ ├── oauth2-example/ # OAuth2完整示例 🆕
│ ├── annotation/ # 注解使用
│ ├── jwt-example/ # JWT示例
│ ├── redis-example/ # Redis示例
│ ├── listener-example/ # 事件监听示例
│ └── gin/echo/fiber/chi/ # 框架集成示例
│
└── docs/ # 文档
├── tutorial/ # 教程
├── guide/ # 使用指南
├── api/ # API文档
└── design/ # 设计文档
🔧 核心API
登录认证
// 登录(支持 int, int64, uint, string)
token, _ := stputil.Login(1000)
token, _ := stputil.Login("user123")
token, _ := stputil.Login(1000, "mobile") // 指定设备
// 检查登录(自动异步续签)
isLogin := stputil.IsLogin(token)
// 获取登录ID
loginID, _ := stputil.GetLoginID(token)
// 登出
stputil.Logout(1000)
stputil.LogoutByToken(token)
// 踢人下线
stputil.Kickout(1000)
stputil.Kickout(1000, "mobile")
JWT Token 支持
// 使用 JWT Token
stputil.SetManager(
core.NewBuilder().
Storage(memory.NewStorage()).
TokenStyle(core.TokenStyleJWT). // 使用 JWT
JwtSecretKey("your-256-bit-secret"). // JWT 密钥
Timeout(3600). // 1小时过期
Build(),
)
// 登录后获得 JWT Token
token, _ := stputil.Login(1000)
// 返回格式:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
// JWT Token 包含用户信息,可在 https://jwt.io 解析
支持的 Token 风格:
TokenStyleUUID- UUID(默认)TokenStyleSimple- 简单随机字符串(16字符)TokenStyleRandom32/64/128- 指定长度随机串(32/64/128字符)TokenStyleJWT- JWT Token(推荐用于分布式)TokenStyleHash- SHA256哈希风格(64字符,高安全性)🆕TokenStyleTimestamp- 时间戳风格(格式:时间戳_loginID_随机数)🆕TokenStyleTik- Tik短ID风格(11字符,类似抖音)🆕
权限验证
// 设置权限
stputil.SetPermissions(1000, []string{
"user:read",
"user:write",
"admin:*", // 通配符:匹配所有admin权限
})
// 检查权限
hasPermission := stputil.HasPermission(1000, "user:read")
hasPermission := stputil.HasPermission(1000, "admin:delete") // 通配符匹配
// 多权限检查
hasAll := stputil.HasPermissionsAnd(1000, []string{"user:read", "user:write"}) // AND逻辑
hasAny := stputil.HasPermissionsOr(1000, []string{"admin", "super"}) // OR逻辑
角色管理
// 设置角色
stputil.SetRoles(1000, []string{"admin", "manager"})
// 检查角色
hasRole := stputil.HasRole(1000, "admin")
// 多角色检查
hasAll := stputil.HasRolesAnd(1000, []string{"admin", "manager"})
hasAny := stputil.HasRolesOr(1000, []string{"admin", "super"})
账号封禁
// 封禁1小时
stputil.Disable(1000, 1*time.Hour)
// 永久封禁
stputil.Disable(1000, 0)
// 解封
stputil.Untie(1000)
// 检查是否被封禁
isDisabled := stputil.IsDisable(1000)
// 获取剩余封禁时间
remainingTime, _ := stputil.GetDisableTime(1000)
Session管理
// 获取Session
sess, _ := stputil.GetSession(1000)
// 设置数据
sess.Set("nickname", "张三")
sess.Set("age", 25)
// 读取数据
nickname := sess.GetString("nickname")
age := sess.GetInt("age")
// 删除数据
sess.Delete("nickname")
// 删除Session
stputil.DeleteSession(1000)
🎨 注解装饰器(Gin框架)
支持的注解
| 注解 | 说明 | 示例 |
|---|---|---|
@SaIgnore |
忽略认证 | sagin.Ignore() |
@SaCheckLogin |
检查登录 | sagin.CheckLogin() |
@SaCheckRole |
检查角色 | sagin.CheckRole("admin") |
@SaCheckPermission |
检查权限 | sagin.CheckPermission("admin:*") |
@SaCheckDisable |
检查封禁 | sagin.CheckDisable() |
使用示例
import sagin "github.com/click33/sa-token-go/integrations/gin"
func main() {
r := gin.Default()
// 公开访问 - 忽略认证
r.GET("/public", sagin.Ignore(), publicHandler)
// 需要登录
r.GET("/user/info", sagin.CheckLogin(), userInfoHandler)
// 需要管理员权限
r.GET("/admin", sagin.CheckPermission("admin:*"), adminHandler)
// 需要多个权限之一(OR逻辑)
r.GET("/user-or-admin",
sagin.CheckPermission("user:read", "admin:*"),
userOrAdminHandler)
// 需要管理员角色
r.GET("/manager", sagin.CheckRole("admin"), managerHandler)
// 检查账号是否被封禁
r.GET("/sensitive", sagin.CheckDisable(), sensitiveHandler)
r.Run(":8080")
}
📚 详细文档
语言切换
使用指南
- 快速开始 - 5分钟上手
- 登录认证 - 登录认证详解
- 权限验证 - 权限系统详解
- 注解使用 - 装饰器模式详解
- 事件监听 - 事件系统详解
- JWT 使用 - JWT Token 详解
- Redis 存储 - Redis 存储配置
API文档
- StpUtil API - 全局工具类完整API
设计文档
存储
📖 示例项目
| 示例 | 说明 | 路径 |
|---|---|---|
| ⚡ 快速开始 | Builder+StpUtil最简使用 | examples/quick-start/ |
| 🎨 Token风格 | 9种Token生成风格演示 | examples/token-styles/ |
| 🔒 安全特性 | Nonce/RefreshToken/OAuth2 | examples/security-features/ |
| 🔐 OAuth2示例 | 完整OAuth2授权码流程 | examples/oauth2-example/ |
| 📝 注解使用 | 装饰器模式详解 | examples/annotation/ |
| 🔑 JWT示例 | JWT Token使用 | examples/jwt-example/ |
| 💾 Redis示例 | Redis存储配置 | examples/redis-example/ |
| 🎧 事件监听 | 事件系统使用 | examples/listener-example/ |
| 🌐 Gin集成 | Gin框架完整集成 | examples/gin/ |
| 🌐 Echo集成 | Echo框架集成 | examples/echo/ |
| 🌐 Fiber集成 | Fiber框架集成 | examples/fiber/ |
| 🌐 Chi集成 | Chi框架集成 | examples/chi/ |
📄 许可证
Apache License 2.0
🙏 致谢
参考 sa-token 设计
Sa-Token-Go v0.1.0