Files
sa-token-go/README_zh.md
2025-11-09 10:59:46 +07:00

20 KiB
Raw Blame History

Sa-Token-Go

中文文档 | English

Go Version License

一个轻量级、高性能的 Go 权限认证框架,参考 sa-token 设计。

核心特性

  • 🔐 登录认证 - 支持多设备登录、Token管理
  • 🛡️ 权限验证 - 细粒度权限控制、通配符支持(*, user:*, user:*:view
  • 👥 角色管理 - 灵活的角色授权机制
  • 🚫 账号封禁 - 临时/永久封禁功能
  • 👢 踢人下线 - 强制用户下线、多端互斥登录
  • 💾 Session会话 - 完整的Session管理
  • 活跃检测 - 自动检测Token活跃度
  • 🔄 自动续期 - Token异步自动续期性能提升400%
  • 🎨 注解支持 - @SaCheckLogin@SaCheckRole@SaCheckPermission
  • 🎧 事件监听 - 强大的事件系统、支持优先级、异步执行
  • 📦 模块化设计 - 按需导入、最小依赖
  • 🔒 Nonce防重放 - 防止请求重放攻击、一次性令牌
  • 🔄 Refresh Token - 刷新令牌机制、无感刷新
  • 🔐 OAuth2 - 完整的OAuth2授权码模式实现

🚀 快速开始

📥 安装

方式一:简化导入(推荐)

只需导入一个框架集成包,自动包含 core 和 stputil 功能!

# 只导入框架集成包(自动包含 core + stputil
go get github.com/click33/sa-token-go/integrations/gin@v0.1.3    # Gin框架
# 或
go get github.com/click33/sa-token-go/integrations/echo@v0.1.3   # Echo框架
# 或
go get github.com/click33/sa-token-go/integrations/fiber@v0.1.3  # Fiber框架
# 或
go get github.com/click33/sa-token-go/integrations/chi@v0.1.3    # Chi框架
# 或
go get github.com/click33/sa-token-go/integrations/gf@v0.1.3     # GoFrame框架

# 存储模块(选一个)
go get github.com/click33/sa-token-go/storage/memory@v0.1.3  # 内存存储(开发)
go get github.com/click33/sa-token-go/storage/redis@v0.1.3   # Redis存储生产

方式二:分开导入

# 核心模块
go get github.com/click33/sa-token-go/core@v0.1.3
go get github.com/click33/sa-token-go/stputil@v0.1.3

# 存储模块(选一个)
go get github.com/click33/sa-token-go/storage/memory@v0.1.3  # 内存存储(开发)
go get github.com/click33/sa-token-go/storage/redis@v0.1.3   # Redis存储生产

# 框架集成(可选)
go get github.com/click33/sa-token-go/integrations/gin@v0.1.3    # Gin框架
go get github.com/click33/sa-token-go/integrations/echo@v0.1.3   # Echo框架
go get github.com/click33/sa-token-go/integrations/fiber@v0.1.3  # Fiber框架
go get github.com/click33/sa-token-go/integrations/chi@v0.1.3    # Chi框架
go get github.com/click33/sa-token-go/integrations/gf@v0.1.3     # GoFrame框架

超简洁使用(一行初始化)

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.3)
:: 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)
}

🔧 核心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")

🛡️ 权限验证

// 设置权限
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管理

// 获取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)

🌐 框架集成

🌟 Gin 集成(单一导入)

新方式:只导入 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 集成(单一导入)

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 同样支持注解装饰器:

// 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)

🎨 高级特性

🎨 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类似抖音

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...

👉 查看 Token 风格示例

🔒 安全特性

🔐 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",
)

👉 查看 OAuth2 完整示例

🎧 事件监听

监听认证和授权事件,实现审计日志、安全监控等功能:

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/
├── 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/             # 设计文档

📚 文档与示例

📖 详细文档

📋 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/
🌐 GoFrame集成 GoFrame框架集成 examples/gf/

💾 存储方案

📄 许可证

Apache License 2.0

🙏 致谢

参考 sa-token 设计

📞 支持