logo
0
0
WeChat Login
c<23@g>
chore: upgrade version to v0.1.6

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)
  • 🛣️ Path-Based Auth - Flexible path-based authentication with Ant-style wildcards
  • 👥 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@latest # Gin framework # or go get github.com/click33/sa-token-go/integrations/echo@latest # Echo framework # or go get github.com/click33/sa-token-go/integrations/fiber@latest # Fiber framework # or go get github.com/click33/sa-token-go/integrations/chi@latest # Chi framework # or go get github.com/click33/sa-token-go/integrations/gf@latest # GoFrame framework # or go get github.com/click33/sa-token-go/integrations/kratos@latest # Kratos framework # Storage module (choose one) go get github.com/click33/sa-token-go/storage/memory@latest # Memory storage (dev) go get github.com/click33/sa-token-go/storage/redis@latest # Redis storage (prod)

Option 2: Separate Import

# Core modules go get github.com/click33/sa-token-go/core@vlatest go get github.com/click33/sa-token-go/stputil@vlatest # Storage module (choose one) go get github.com/click33/sa-token-go/storage/memory@latest # Memory storage (dev) go get github.com/click33/sa-token-go/storage/redis@latest # Redis storage (prod) # Framework integration (optional) go get github.com/click33/sa-token-go/integrations/gin@latest # Gin framework go get github.com/click33/sa-token-go/integrations/echo@latest # Echo framework go get github.com/click33/sa-token-go/integrations/fiber@latest # Fiber framework go get github.com/click33/sa-token-go/integrations/chi@latest # Chi framework go get github.com/click33/sa-token-go/integrations/gf@latest # GoFrame framework go get github.com/click33/sa-token-go/integrations/kratos@latest# Kratos 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.6) :: 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:

AnnotationDescriptionExample
@SaIgnoreIgnore authenticationsagin.Ignore()
@SaCheckLoginCheck loginsagin.CheckLogin()
@SaCheckRoleCheck rolesagin.CheckRole("admin")
@SaCheckPermissionCheck permissionsagin.CheckPermission("admin:*")
@SaCheckDisableCheck if disabledsagin.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 / Kratos 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) // Kratos import sakratos "github.com/click33/sa-token-go/integrations/kratos" // Use Plugin.Server() as middleware

🎨 Advanced Features

🎨 Token Styles

Sa-Token-Go supports 9 token generation styles:

StyleFormat ExampleLengthUse Case
UUID550e8400-e29b-41d4-...36General purpose
SimpleaB3dE5fG7hI9jK1l16Compact tokens
Random32/64/128Random string32/64/128High security
JWTeyJhbGciOiJIUzI1...VariableStateless auth
Hash 🆕a3f5d8b2c1e4f6a9...64SHA256 hash
Timestamp 🆕1700000000123_user1000_...VariableTime traceable
Tik 🆕7Kx9mN2pQr411Short 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:

storage := memory.NewStorage() manager := core.NewBuilder(). Storage(storage). Build() // Listen to login events manager.RegisterFunc(core.EventLogin, func(data *core.EventData) { fmt.Printf("[LOGIN] User: %s, Token: %s\n", data.LoginID, data.Token) }) // Listen to logout events manager.RegisterFunc(core.EventLogout, func(data *core.EventData) { fmt.Printf("[LOGOUT] User: %s\n", data.LoginID) }) // Advanced: priority and sync execution manager.RegisterWithConfig(core.EventLogin, core.ListenerFunc(auditLogger), core.ListenerConfig{ Priority: 100, // High priority Async: false, // Sync execution }, ) // Listen to all events (wildcard) manager.RegisterFunc(core.EventAll, func(data *core.EventData) { log.Printf("[%s] %s", data.Event, data.LoginID) }) // Access advanced controls via the underlying EventManager manager.GetEventManager().SetPanicHandler(customPanicHandler) // Use the manager globally stputil.SetManager(manager)

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

ExampleDescriptionPath
⚡ Quick StartBuilder+StpUtil minimal usageexamples/quick-start/
🎨 Token Styles9 token style demonstrationsexamples/token-styles/
🔒 Security FeaturesNonce/RefreshToken/OAuth2examples/security-features/
🔐 OAuth2 ExampleComplete OAuth2 implementationexamples/oauth2-example/
📝 AnnotationsAnnotation usage exampleexamples/annotation/
🔑 JWT ExampleJWT token usageexamples/jwt-example/
💾 Redis ExampleRedis storage exampleexamples/redis-example/
🎧 Event ListenerEvent system usageexamples/listener-example/
🌐 Gin IntegrationComplete Gin integrationexamples/gin/
🌐 Echo IntegrationEcho framework integrationexamples/echo/
🌐 Fiber IntegrationFiber framework integrationexamples/fiber/
🌐 Chi IntegrationChi framework integrationexamples/chi/
🌐 GoFrame IntegrationGoFrame framework integrationexamples/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

Contributors

Special thanks to the following contributors for their valuable contributions:

📞 Support