Skip to content

sa-token for golang 一个轻量级 go 权限认证框架,让鉴权变得简单优雅

License

Notifications You must be signed in to change notification settings

idslee/sa-token-go

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Sa-Token-Go

English | 中文

Go Version License

A lightweight, high-performance Go authentication and authorization framework, inspired by sa-token.

✨ Core Features

  • 🔐 Authentication - Multi-device login, Token management
  • 🛡️ Authorization - Fine-grained permission control, wildcard support (*, user:*, user:*:view)
  • 👥 Role Management - Flexible role authorization mechanism
  • 🚫 Account Ban - Temporary/permanent account disabling
  • 👢 Kickout - Force user logout, multi-device mutual exclusion
  • 💾 Session Management - Complete Session management
  • Active Detection - Automatic token activity detection
  • 🔄 Auto Renewal - Asynchronous token auto-renewal (400% performance improvement)
  • 🎨 Annotation Support - @SaCheckLogin, @SaCheckRole, @SaCheckPermission
  • 🎧 Event System - Powerful event system with priority and async execution
  • 📦 Modular Design - Import only what you need, minimal dependencies
  • 🔒 Nonce Anti-Replay - Prevent replay attacks with one-time tokens
  • 🔄 Refresh Token - Refresh token mechanism with seamless refresh
  • 🔐 OAuth2 - Complete OAuth2 authorization code flow implementation

🚀 Quick Start

📥 Installation

Option 1: Simplified Import (Recommended) ✨

Import only one framework integration package, which automatically includes core and stputil!

# Import only the framework integration (includes core + stputil automatically)
go get github.com/click33/sa-token-go/integrations/gin@v0.1.2    # Gin framework
# or
go get github.com/click33/sa-token-go/integrations/echo@v0.1.2   # Echo framework
# or
go get github.com/click33/sa-token-go/integrations/fiber@v0.1.2  # Fiber framework
# or
go get github.com/click33/sa-token-go/integrations/chi@v0.1.2    # Chi framework
# or
go get github.com/click33/sa-token-go/integrations/gf@v0.1.2     # GoFrame framework

# Storage module (choose one)
go get github.com/click33/sa-token-go/storage/memory@v0.1.2  # Memory storage (dev)
go get github.com/click33/sa-token-go/storage/redis@v0.1.2   # Redis storage (prod)

Option 2: Separate Import

# Core modules
go get github.com/click33/sa-token-go/core@v0.1.2
go get github.com/click33/sa-token-go/stputil@v0.1.2

# Storage module (choose one)
go get github.com/click33/sa-token-go/storage/memory@v0.1.2  # Memory storage (dev)
go get github.com/click33/sa-token-go/storage/redis@v0.1.2   # Redis storage (prod)

# Framework integration (optional)
go get github.com/click33/sa-token-go/integrations/gin@v0.1.2    # Gin framework
go get github.com/click33/sa-token-go/integrations/echo@v0.1.2   # Echo framework
go get github.com/click33/sa-token-go/integrations/fiber@v0.1.2  # Fiber framework
go get github.com/click33/sa-token-go/integrations/chi@v0.1.2    # Chi framework

⚡ Minimal Usage (One-line Initialization)

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() {
    // One-line initialization! Shows startup banner
    stputil.SetManager(
        core.NewBuilder().
            Storage(memory.NewStorage()).
            TokenName("Authorization").
            Timeout(86400).                      // 24 hours
            TokenStyle(core.TokenStyleRandom64). // Token style
            IsPrintBanner(true).                 // Show startup banner
            Build(),
    )
}

Startup banner will be displayed:

   _____         ______      __                  ______     
  / ___/____ _  /_  __/___  / /_____  ____      / ____/____ 
  \__ \/ __  |   / / / __ \/ //_/ _ \/ __ \_____/ / __/ __ \
 ___/ / /_/ /   / / / /_/ / ,< /  __/ / / /_____/ /_/ / /_/ /
/____/\__,_/   /_/  \____/_/|_|\___/_/ /_/      \____/\____/ 
                                                             
:: Sa-Token-Go ::                                    (v0.1.2)
:: Go Version ::                                     go1.21.0
:: GOOS/GOARCH ::                                    linux/amd64

┌─────────────────────────────────────────────────────────┐
│ Token Style     : random64                              │
│ Token Timeout   : 86400                      seconds    │
│ Auto Renew      : true                                  │
└─────────────────────────────────────────────────────────┘
func main() {
    // Use StpUtil directly without passing manager
    token, _ := stputil.Login(1000)
    println("Login successful, Token:", token)
    
    // Set permissions
    stputil.SetPermissions(1000, []string{"user:read", "user:write"})
    
    // Check permissions
    if stputil.HasPermission(1000, "user:read") {
        println("Has permission!")
    }
    
    // Logout
    stputil.Logout(1000)
}

🔧 Core API

🔑 Authentication

// Login
token, _ := stputil.Login(1000)
token, _ := stputil.Login("user123")
token, _ := stputil.Login(1000, "mobile")  // Specify device

// Check login status
isLogin := stputil.IsLogin(token)

// Get login ID
loginID, _ := stputil.GetLoginID(token)

// Logout
stputil.Logout(1000)
stputil.LogoutByToken(token)

// Kickout
stputil.Kickout(1000)
stputil.Kickout(1000, "mobile")

🛡️ Permission Management

// Set permissions
stputil.SetPermissions(1000, []string{
    "user:read",
    "user:write",
    "admin:*",  // Wildcard: matches all admin permissions
})

// Check single permission
hasPermission := stputil.HasPermission(1000, "user:read")
hasPermission := stputil.HasPermission(1000, "admin:delete")  // Wildcard match

// Check multiple permissions
hasAll := stputil.HasPermissionsAnd(1000, []string{"user:read", "user:write"})  // AND logic
hasAny := stputil.HasPermissionsOr(1000, []string{"admin", "super"})           // OR logic

👥 Role Management

// Set roles
stputil.SetRoles(1000, []string{"admin", "manager"})

// Check role
hasRole := stputil.HasRole(1000, "admin")

// Check multiple roles
hasAll := stputil.HasRolesAnd(1000, []string{"admin", "manager"})
hasAny := stputil.HasRolesOr(1000, []string{"admin", "super"})

💾 Session Management

// Get session
sess, _ := stputil.GetSession(1000)

// Set data
sess.Set("nickname", "John")
sess.Set("age", 25)

// Get data
nickname := sess.GetString("nickname")
age := sess.GetInt("age")

// Delete data
sess.Delete("nickname")

// Delete session
stputil.DeleteSession(1000)

🚫 Account Management

// Disable for 1 hour
stputil.Disable(1000, 1*time.Hour)

// Permanent disable
stputil.Disable(1000, 0)

// Enable account
stputil.Untie(1000)

// Check if disabled
isDisabled := stputil.IsDisable(1000)

// Get remaining disable time
remainingTime, _ := stputil.GetDisableTime(1000)

🌐 Framework Integration

🌟 Gin Integration (Single Import)

New way: Import only integrations/gin to use all features!

import (
    "github.com/gin-gonic/gin"
    sagin "github.com/click33/sa-token-go/integrations/gin"  // Only this import needed!
    "github.com/click33/sa-token-go/storage/memory"
)

func main() {
    // Initialize (all features in sagin package)
    storage := memory.NewStorage()
    config := sagin.DefaultConfig()
    manager := sagin.NewManager(storage, config)
    sagin.SetManager(manager)
    
    r := gin.Default()
    
    // Login endpoint
    r.POST("/login", func(c *gin.Context) {
        userID := c.PostForm("user_id")
        token, _ := sagin.Login(userID)
        c.JSON(200, gin.H{"token": token})
    })
    
    // Use annotation-style decorators (like Java)
    r.GET("/public", sagin.Ignore(), publicHandler)                  // Public access
    r.GET("/user", sagin.CheckLogin(), userHandler)                  // Login required
    r.GET("/admin", sagin.CheckPermission("admin:*"), adminHandler)  // Permission required
    r.GET("/manager", sagin.CheckRole("manager"), managerHandler)    // Role required
    r.GET("/sensitive", sagin.CheckDisable(), sensitiveHandler)      // Check if disabled
    
    r.Run(":8080")
}

🎯 Annotation Decorators

Supported annotations:

Annotation Description Example
@SaIgnore Ignore authentication sagin.Ignore()
@SaCheckLogin Check login sagin.CheckLogin()
@SaCheckRole Check role sagin.CheckRole("admin")
@SaCheckPermission Check permission sagin.CheckPermission("admin:*")
@SaCheckDisable Check if disabled sagin.CheckDisable()

Usage example:

import sagin "github.com/click33/sa-token-go/integrations/gin"

func main() {
    r := gin.Default()

    // Public access - ignore authentication
    r.GET("/public", sagin.Ignore(), publicHandler)

    // Login required
    r.GET("/user/info", sagin.CheckLogin(), userInfoHandler)

    // Admin permission required
    r.GET("/admin", sagin.CheckPermission("admin:*"), adminHandler)

    // Any of multiple permissions (OR logic)
    r.GET("/user-or-admin",
        sagin.CheckPermission("user:read", "admin:*"),
        userOrAdminHandler)

    // Admin role required
    r.GET("/manager", sagin.CheckRole("admin"), managerHandler)

    // Check if account is disabled
    r.GET("/sensitive", sagin.CheckDisable(), sensitiveHandler)

    r.Run(":8080")
}

🌟 GoFrame Integration (Single Import)

GoFrame framework integration with full feature support!

import (
    "github.com/gogf/gf/v2/frame/g"
    "github.com/gogf/gf/v2/net/ghttp"
    sagf "github.com/click33/sa-token-go/integrations/gf"  // Only this import needed!
    "github.com/click33/sa-token-go/storage/memory"
)

func main() {
    // Initialize (all features in sagf package)
    storage := memory.NewStorage()
    config := sagf.DefaultConfig()
    manager := sagf.NewManager(storage, config)
    sagf.SetManager(manager)
    
    s := g.Server()
    
    // Login endpoint
    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})
    })
    
    // Use annotation-style decorators (like Java)
    s.BindHandler("GET:/public", sagf.Ignore(), publicHandler)                  // Public access
    s.BindHandler("GET:/user", sagf.CheckLogin(), userHandler)                  // Login required
    s.BindHandler("GET:/admin", sagf.CheckPermission("admin:*"), adminHandler)  // Permission required
    s.BindHandler("GET:/manager", sagf.CheckRole("manager"), managerHandler)    // Role required
    s.BindHandler("GET:/sensitive", sagf.CheckDisable(), sensitiveHandler)      // Check if disabled
    
    s.SetPort(8080)
    s.Run()
}

🔌 Other Framework Integrations

Echo / Fiber / Chi also support annotation decorators:

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

🎨 Advanced Features

🎨 Token Styles

Sa-Token-Go supports 9 token generation styles:

Style Format Example Length Use Case
UUID 550e8400-e29b-41d4-... 36 General purpose
Simple aB3dE5fG7hI9jK1l 16 Compact tokens
Random32/64/128 Random string 32/64/128 High security
JWT eyJhbGciOiJIUzI1... Variable Stateless auth
Hash 🆕 a3f5d8b2c1e4f6a9... 64 SHA256 hash
Timestamp 🆕 1700000000123_user1000_... Variable Time traceable
Tik 🆕 7Kx9mN2pQr4 11 Short ID (like TikTok)

JWT Token Support:

// Use JWT Token
stputil.SetManager(
    core.NewBuilder().
        Storage(memory.NewStorage()).
        TokenStyle(core.TokenStyleJWT).          // Use JWT
        JwtSecretKey("your-256-bit-secret").     // JWT secret
        Timeout(3600).                           // 1 hour expiration
        Build(),
)

// Login to get JWT Token
token, _ := stputil.Login(1000)
// Format: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

👉 View Token Style Examples

🔒 Security Features

🔐 Nonce Anti-Replay Attack

// Generate nonce
nonce, _ := stputil.GenerateNonce()

// Verify nonce (one-time use)
valid := stputil.VerifyNonce(nonce)  // true
valid = stputil.VerifyNonce(nonce)   // false (prevents replay)

🔄 Refresh Token Mechanism

// Login to get access token and refresh token
tokenInfo, _ := stputil.LoginWithRefreshToken(1000, "web")
fmt.Println("Access Token:", tokenInfo.AccessToken)
fmt.Println("Refresh Token:", tokenInfo.RefreshToken)

// Refresh access token
newInfo, _ := stputil.RefreshAccessToken(tokenInfo.RefreshToken)

🔑 OAuth2 Authorization Code Flow

// Create OAuth2 server
oauth2Server := stputil.GetOAuth2Server()

// Register client
oauth2Server.RegisterClient(&core.OAuth2Client{
    ClientID:     "webapp",
    ClientSecret: "secret123",
    RedirectURIs: []string{"http://localhost:8080/callback"},
    GrantTypes:   []core.OAuth2GrantType{core.GrantTypeAuthorizationCode},
    Scopes:       []string{"read", "write"},
})

// Generate authorization code
authCode, _ := oauth2Server.GenerateAuthorizationCode(
    "webapp", "http://localhost:8080/callback", "user123", []string{"read"},
)

// Exchange authorization code for access token
accessToken, _ := oauth2Server.ExchangeCodeForToken(
    authCode.Code, "webapp", "secret123", "http://localhost:8080/callback",
)

👉 View Complete OAuth2 Example

🎧 Event System

Listen to authentication and authorization events for audit logging, security monitoring, etc:

// Create event manager
eventMgr := core.NewEventManager()

// Listen to login events
eventMgr.RegisterFunc(core.EventLogin, func(data *core.EventData) {
    fmt.Printf("[LOGIN] User: %s, Token: %s\n", data.LoginID, data.Token)
    // Log audit, send notifications, etc.
})

// Listen to logout events
eventMgr.RegisterFunc(core.EventLogout, func(data *core.EventData) {
    fmt.Printf("[LOGOUT] User: %s\n", data.LoginID)
})

// Advanced: priority and sync execution
eventMgr.RegisterWithConfig(core.EventLogin,
    core.ListenerFunc(auditLogger),
    core.ListenerConfig{
        Priority: 100,   // High priority
        Async:    false, // Sync execution
    },
)

// Listen to all events (wildcard)
eventMgr.RegisterFunc(core.EventAll, func(data *core.EventData) {
    log.Printf("[%s] %s", data.Event, data.LoginID)
})

Available events:

  • EventLogin - User login
  • EventLogout - User logout
  • EventKickout - Force logout
  • EventDisable - Account ban
  • EventPermissionCheck - Permission check
  • EventRoleCheck - Role check
  • EventAll - All events (wildcard)

→ View Event System Documentation

📦 Project Structure

sa-token-go/
├── core/                    # Core module
│   ├── adapter/            # Adapter interfaces
│   ├── builder/            # Builder pattern
│   ├── config/             # Configuration
│   ├── context/            # Context
│   ├── listener/           # Event listener
│   ├── manager/            # Authentication manager
│   ├── oauth2/             # OAuth2 implementation 🆕
│   ├── security/           # Security features (Nonce, RefreshToken) 🆕
│   ├── session/            # Session management
│   ├── token/              # Token generator
│   └── utils/              # Utility functions
│
├── stputil/                # Global utility
│
├── storage/                # Storage modules
│   ├── memory/             # Memory storage
│   └── redis/              # Redis storage
│
├── integrations/           # Framework integrations
│   ├── gin/                # Gin integration (with annotations)
│   ├── echo/               # Echo integration
│   ├── fiber/              # Fiber integration
│   └── chi/                # Chi integration
│
├── examples/               # Example projects
│   ├── quick-start/        # Quick start
│   ├── token-styles/       # Token style demos 🆕
│   ├── security-features/  # Security features demos 🆕
│   ├── oauth2-example/     # Complete OAuth2 example 🆕
│   ├── annotation/         # Annotation usage
│   ├── jwt-example/        # JWT example
│   ├── redis-example/      # Redis example
│   ├── listener-example/   # Event listener example
│   └── gin/echo/fiber/chi/ # Framework integration examples
│
└── docs/                   # Documentation
    ├── tutorial/           # Tutorials
    ├── guide/              # Usage guides
    ├── api/                # API documentation
    └── design/             # Design documents

📚 Documentation & Examples

📖 Documentation

📋 API Reference

🏗️ Design Documentation

💡 Example Projects

Example Description Path
⚡ Quick Start Builder+StpUtil minimal usage examples/quick-start/
🎨 Token Styles 9 token style demonstrations examples/token-styles/
🔒 Security Features Nonce/RefreshToken/OAuth2 examples/security-features/
🔐 OAuth2 Example Complete OAuth2 implementation examples/oauth2-example/
📝 Annotations Annotation usage example examples/annotation/
🔑 JWT Example JWT token usage examples/jwt-example/
💾 Redis Example Redis storage example examples/redis-example/
🎧 Event Listener Event system usage examples/listener-example/
🌐 Gin Integration Complete Gin integration examples/gin/
🌐 Echo Integration Echo framework integration examples/echo/
🌐 Fiber Integration Fiber framework integration examples/fiber/
🌐 Chi Integration Chi framework integration examples/chi/
🌐 GoFrame Integration GoFrame framework integration examples/gf/

💾 Storage Options

📄 License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

🙏 Acknowledgments

  • Inspired by sa-token - A powerful Java authentication framework
  • Built with ❤️ using Go

📞 Support


About

sa-token for golang 一个轻量级 go 权限认证框架,让鉴权变得简单优雅

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Go 100.0%