中文文档 | English
一个轻量级、高性能的 Go 权限认证框架,参考 sa-token 设计。
*, user:*, user:*:view)@SaCheckLogin、@SaCheckRole、@SaCheckPermission只需导入一个框架集成包,自动包含 core 和 stputil 功能!
# 只导入框架集成包(自动包含 core + stputil)
go get github.com/click33/sa-token-go/integrations/gin@latest # Gin框架
# 或
go get github.com/click33/sa-token-go/integrations/echo@latest # Echo框架
# 或
go get github.com/click33/sa-token-go/integrations/fiber@latest # Fiber框架
# 或
go get github.com/click33/sa-token-go/integrations/chi@latest # Chi框架
# 或
go get github.com/click33/sa-token-go/integrations/gf@latest # GoFrame框架
# 或
go get github.com/click33/sa-token-go/integrations/kratos@latest# Kratos框架
# 存储模块(选一个)
go get github.com/click33/sa-token-go/storage/memory@latest # 内存存储(开发)
go get github.com/click33/sa-token-go/storage/redis@latest # Redis存储(生产)
# 核心模块
go get github.com/click33/sa-token-go/core@vlatest
go get github.com/click33/sa-token-go/stputil@vlatest
# 存储模块(选一个)
go get github.com/click33/sa-token-go/storage/memory@latest # 内存存储(开发)
go get github.com/click33/sa-token-go/storage/redis@latest # Redis存储(生产)
# 框架集成(可选)
go get github.com/click33/sa-token-go/integrations/gin@latest # Gin框架
go get github.com/click33/sa-token-go/integrations/echo@latest # Echo框架
go get github.com/click33/sa-token-go/integrations/fiber@latest # Fiber框架
go get github.com/click33/sa-token-go/integrations/chi@latest # Chi框架
go get github.com/click33/sa-token-go/integrations/gf@latest # GoFrame框架
go get github.com/click33/sa-token-go/integrations/kratos@latest# Kratos框架
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.6) :: Go Version :: go1.21.0 :: GOOS/GOARCH :: linux/amd64 ┌─────────────────────────────────────────────────────────┐ │ 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)
}
// 登录(支持 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")
// 设置权限
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"})
// 获取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)
// 封禁1小时
stputil.Disable(1000, 1*time.Hour)
// 永久封禁
stputil.Disable(1000, 0)
// 解封
stputil.Untie(1000)
// 检查是否被封禁
isDisabled := stputil.IsDisable(1000)
// 获取剩余封禁时间
remainingTime, _ := stputil.GetDisableTime(1000)
新方式:只导入 integrations/gin 即可使用所有功能!
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")
}
支持的注解:
| 注解 | 说明 | 示例 |
|---|---|---|
@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")
}
GoFrame 框架集成,支持完整功能!
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
sagf "github.com/click33/sa-token-go/integrations/gf" // 只需这一个导入!
"github.com/click33/sa-token-go/storage/memory"
)
func main() {
// 初始化(sagf 包包含所有功能)
storage := memory.NewStorage()
config := sagf.DefaultConfig()
manager := sagf.NewManager(storage, config)
sagf.SetManager(manager)
s := g.Server()
// 登录接口
s.BindHandler("POST:/login", func(r *ghttp.Request) {
userID := r.Get("user_id").String()
token, _ := sagf.Login(userID)
r.Response.WriteJson(g.Map{"token": token})
})
// 使用注解式装饰器(类似 Java)
s.BindHandler("GET:/public", sagf.Ignore(), publicHandler) // 公开访问
s.BindHandler("GET:/user", sagf.CheckLogin(), userHandler) // 需要登录
s.BindHandler("GET:/admin", sagf.CheckPermission("admin:*"), adminHandler) // 需要权限
s.BindHandler("GET:/manager", sagf.CheckRole("manager"), managerHandler) // 需要角色
s.BindHandler("GET:/sensitive", sagf.CheckDisable(), sensitiveHandler) // 检查是否禁用
s.SetPort(8080)
s.Run()
}
Echo / Fiber / Chi / Kratos 同样支持注解装饰器:
// Echo
import saecho "github.com/click33/sa-token-go/integrations/echo"
e.GET("/user", saecho.CheckLogin(), handler)
// Fiber
import safiber "github.com/click33/sa-token-go/integrations/fiber"
app.Get("/user", safiber.CheckLogin(), handler)
// Chi
import sachi "github.com/click33/sa-token-go/integrations/chi"
r.Get("/user", sachi.CheckLogin(), handler)
// Kratos
import sakratos "github.com/click33/sa-token-go/integrations/kratos"
// 使用 Plugin.Server() 作为中间件
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(类似抖音) |
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...
// 生成nonce
nonce, _ := stputil.GenerateNonce()
// 验证nonce(一次性使用)
valid := stputil.VerifyNonce(nonce) // true
valid = stputil.VerifyNonce(nonce) // false(防止重放)
// 登录获取访问令牌和刷新令牌
tokenInfo, _ := stputil.LoginWithRefreshToken(1000, "web")
fmt.Println("Access Token:", tokenInfo.AccessToken)
fmt.Println("Refresh Token:", tokenInfo.RefreshToken)
// 刷新访问令牌
newInfo, _ := stputil.RefreshAccessToken(tokenInfo.RefreshToken)
// 创建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",
)
监听认证和授权事件,实现审计日志、安全监控等功能:
storage := memory.NewStorage()
manager := core.NewBuilder().
Storage(storage).
Build()
// 监听登录事件
manager.RegisterFunc(core.EventLogin, func(data *core.EventData) {
fmt.Printf("[LOGIN] User: %s, Token: %s\n", data.LoginID, data.Token)
// 记录审计日志、发送通知等
})
// 监听登出事件
manager.RegisterFunc(core.EventLogout, func(data *core.EventData) {
fmt.Printf("[LOGOUT] User: %s\n", data.LoginID)
})
// 高级特性:优先级、同步执行
manager.RegisterWithConfig(core.EventLogin,
core.ListenerFunc(auditLogger),
core.ListenerConfig{
Priority: 100, // 高优先级
Async: false, // 同步执行
},
)
// 监听所有事件(通配符)
manager.RegisterFunc(core.EventAll, func(data *core.EventData) {
log.Printf("[%s] %s", data.Event, data.LoginID)
})
// 可通过底层 EventManager 访问更多控制能力
manager.GetEventManager().SetPanicHandler(customPanicHandler)
// 设置全局管理器
stputil.SetManager(manager)
可用事件:
EventLogin - 用户登录EventLogout - 用户登出EventKickout - 强制下线EventDisable - 账号封禁EventPermissionCheck - 权限检查EventRoleCheck - 角色检查EventAll - 所有事件(通配符)下面通过架构图来更直观地理解 sa-token-go 的设计思路和组件关系:
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集成 │ └── gf/ # GoFrame集成 │ ├── 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/ # 设计文档
| 示例 | 说明 | 路径 |
|---|---|---|
| ⚡ 快速开始 | 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/ |
| 🌐 GoFrame集成 | GoFrame框架集成 | examples/gf/ |
Apache License 2.0
参考 sa-token 设计
特别感谢以下贡献者的宝贵贡献: