232 lines
4.5 KiB
Go
232 lines
4.5 KiB
Go
package auth
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/golang-jwt/jwt/v5"
|
|
)
|
|
|
|
// Auth 认证授权系统
|
|
type Auth struct {
|
|
// JWT密钥
|
|
secretKey []byte
|
|
// 用户存储
|
|
users map[string]*User
|
|
// 角色权限映射
|
|
rolePermissions map[string][]string
|
|
// 锁
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
// User 用户信息
|
|
type User struct {
|
|
// 用户名
|
|
Username string
|
|
// 密码
|
|
Password string
|
|
// 角色列表
|
|
Roles []string
|
|
// 创建时间
|
|
CreatedAt time.Time
|
|
// 最后登录时间
|
|
LastLoginAt time.Time
|
|
}
|
|
|
|
// NewAuth 创建认证授权系统
|
|
func NewAuth(secretKey string) *Auth {
|
|
return &Auth{
|
|
secretKey: []byte(secretKey),
|
|
users: make(map[string]*User),
|
|
rolePermissions: make(map[string][]string),
|
|
}
|
|
}
|
|
|
|
// AddUser 添加用户
|
|
func (a *Auth) AddUser(username, password string, roles []string) error {
|
|
a.mu.Lock()
|
|
defer a.mu.Unlock()
|
|
|
|
if _, exists := a.users[username]; exists {
|
|
return fmt.Errorf("用户已存在")
|
|
}
|
|
|
|
// 密码加密
|
|
hashedPassword := hashPassword(password)
|
|
|
|
// 创建用户
|
|
a.users[username] = &User{
|
|
Username: username,
|
|
Password: hashedPassword,
|
|
Roles: roles,
|
|
CreatedAt: time.Now(),
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Authenticate 认证用户
|
|
func (a *Auth) Authenticate(username, password string) (string, error) {
|
|
a.mu.RLock()
|
|
user, exists := a.users[username]
|
|
a.mu.RUnlock()
|
|
|
|
if !exists {
|
|
return "", fmt.Errorf("用户不存在")
|
|
}
|
|
|
|
// 验证密码
|
|
if !a.ValidateUser(username, password) {
|
|
return "", fmt.Errorf("密码错误")
|
|
}
|
|
|
|
// 更新最后登录时间
|
|
a.mu.Lock()
|
|
user.LastLoginAt = time.Now()
|
|
a.mu.Unlock()
|
|
|
|
// 生成JWT令牌
|
|
token, err := a.GenerateToken(username)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return token, nil
|
|
}
|
|
|
|
// Authorize 授权检查
|
|
func (a *Auth) Authorize(token, permission string) error {
|
|
// 验证JWT令牌
|
|
claims, err := a.ValidateToken(token)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 检查用户权限
|
|
a.mu.RLock()
|
|
username, ok := (*claims)["username"].(string)
|
|
if !ok {
|
|
a.mu.RUnlock()
|
|
return fmt.Errorf("无效的用户名")
|
|
}
|
|
user, exists := a.users[username]
|
|
a.mu.RUnlock()
|
|
|
|
if !exists {
|
|
return fmt.Errorf("用户不存在")
|
|
}
|
|
|
|
// 检查用户角色权限
|
|
for _, role := range user.Roles {
|
|
if a.hasPermission(role, permission) {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("权限不足")
|
|
}
|
|
|
|
// Middleware 认证中间件
|
|
func (a *Auth) Middleware(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
// 获取认证头
|
|
authHeader := r.Header.Get("Authorization")
|
|
if authHeader == "" {
|
|
http.Error(w, "未提供认证信息", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
// 解析Bearer令牌
|
|
parts := strings.Split(authHeader, " ")
|
|
if len(parts) != 2 || parts[0] != "Bearer" {
|
|
http.Error(w, "认证格式错误", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
// 验证令牌
|
|
if err := a.Authorize(parts[1], r.URL.Path); err != nil {
|
|
http.Error(w, "认证失败", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
next.ServeHTTP(w, r)
|
|
})
|
|
}
|
|
|
|
// ValidateUser 验证用户
|
|
func (a *Auth) ValidateUser(username, password string) bool {
|
|
a.mu.RLock()
|
|
defer a.mu.RUnlock()
|
|
|
|
user, exists := a.users[username]
|
|
if !exists {
|
|
return false
|
|
}
|
|
|
|
return user.Password == hashPassword(password)
|
|
}
|
|
|
|
// GenerateToken 生成JWT令牌
|
|
func (a *Auth) GenerateToken(username string) (string, error) {
|
|
a.mu.RLock()
|
|
user, exists := a.users[username]
|
|
a.mu.RUnlock()
|
|
|
|
if !exists {
|
|
return "", errors.New("用户不存在")
|
|
}
|
|
|
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
|
"username": username,
|
|
"roles": user.Roles,
|
|
"exp": time.Now().Add(24 * time.Hour).Unix(),
|
|
})
|
|
|
|
return token.SignedString(a.secretKey)
|
|
}
|
|
|
|
// ValidateToken 验证JWT令牌
|
|
func (a *Auth) ValidateToken(tokenString string) (*jwt.MapClaims, error) {
|
|
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
|
return a.secretKey, nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
|
|
return &claims, nil
|
|
}
|
|
|
|
return nil, errors.New("无效的令牌")
|
|
}
|
|
|
|
// hashPassword 密码加密
|
|
func hashPassword(password string) string {
|
|
hash := sha256.New()
|
|
hash.Write([]byte(password))
|
|
return hex.EncodeToString(hash.Sum(nil))
|
|
}
|
|
|
|
// hasPermission 检查角色是否有权限
|
|
func (a *Auth) hasPermission(role, permission string) bool {
|
|
permissions, exists := a.rolePermissions[role]
|
|
if !exists {
|
|
return false
|
|
}
|
|
|
|
for _, p := range permissions {
|
|
if p == permission {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|