Golang实现基于角色的访问控制登录示例

Golang实现基于角色的访问控制登录示例 大家好,

我是Go语言Web开发的新手。

我计划开发一个基于角色的访问控制和身份验证的登录系统,请问是否有相关的示例可供参考?

谢谢

1 回复

更多关于Golang实现基于角色的访问控制登录示例的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


以下是一个基于角色的访问控制(RBAC)登录系统示例,包含用户认证和权限验证:

package main

import (
    "encoding/json"
    "net/http"
    "time"
    
    "github.com/dgrijalva/jwt-go"
    "golang.org/x/crypto/bcrypt"
)

// 用户模型
type User struct {
    ID       int    `json:"id"`
    Username string `json:"username"`
    Password string `json:"password"`
    Role     string `json:"role"`
}

// 角色权限映射
var rolePermissions = map[string][]string{
    "admin":    {"read", "write", "delete", "manage_users"},
    "editor":   {"read", "write"},
    "viewer":   {"read"},
}

// JWT声明
type Claims struct {
    Username string `json:"username"`
    Role     string `json:"role"`
    jwt.StandardClaims
}

// 用户存储(实际项目中应使用数据库)
var users = []User{
    {ID: 1, Username: "admin", Password: hashPassword("admin123"), Role: "admin"},
    {ID: 2, Username: "editor", Password: hashPassword("editor123"), Role: "editor"},
    {ID: 3, Username: "viewer", Password: hashPassword("viewer123"), Role: "viewer"},
}

var jwtKey = []byte("your_secret_key")

func main() {
    http.HandleFunc("/login", loginHandler)
    http.HandleFunc("/protected", authMiddleware(protectedHandler))
    http.HandleFunc("/admin-only", roleMiddleware("admin", adminHandler))
    
    http.ListenAndServe(":8080", nil)
}

// 密码哈希
func hashPassword(password string) string {
    hash, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
    return string(hash)
}

// 密码验证
func checkPassword(password, hash string) bool {
    err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
    return err == nil
}

// 登录处理器
func loginHandler(w http.ResponseWriter, r *http.Request) {
    var creds struct {
        Username string `json:"username"`
        Password string `json:"password"`
    }
    
    if err := json.NewDecoder(r.Body).Decode(&creds); err != nil {
        w.WriteHeader(http.StatusBadRequest)
        return
    }
    
    // 查找用户
    var user *User
    for _, u := range users {
        if u.Username == creds.Username && checkPassword(creds.Password, u.Password) {
            user = &u
            break
        }
    }
    
    if user == nil {
        w.WriteHeader(http.StatusUnauthorized)
        return
    }
    
    // 创建JWT令牌
    expirationTime := time.Now().Add(24 * time.Hour)
    claims := &Claims{
        Username: user.Username,
        Role:     user.Role,
        StandardClaims: jwt.StandardClaims{
            ExpiresAt: expirationTime.Unix(),
        },
    }
    
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    tokenString, err := token.SignedString(jwtKey)
    if err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        return
    }
    
    // 返回令牌
    json.NewEncoder(w).Encode(map[string]string{
        "token": tokenString,
        "role":  user.Role,
    })
}

// 认证中间件
func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        tokenString := r.Header.Get("Authorization")
        if tokenString == "" {
            w.WriteHeader(http.StatusUnauthorized)
            return
        }
        
        claims := &Claims{}
        token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
            return jwtKey, nil
        })
        
        if err != nil || !token.Valid {
            w.WriteHeader(http.StatusUnauthorized)
            return
        }
        
        // 将用户信息存入上下文
        ctx := r.Context()
        r = r.WithContext(ctx)
        next(w, r)
    }
}

// 角色检查中间件
func roleMiddleware(requiredRole string, next http.HandlerFunc) http.HandlerFunc {
    return authMiddleware(func(w http.ResponseWriter, r *http.Request) {
        tokenString := r.Header.Get("Authorization")
        claims := &Claims{}
        jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
            return jwtKey, nil
        })
        
        // 检查角色权限
        if !hasPermission(claims.Role, requiredRole) {
            w.WriteHeader(http.StatusForbidden)
            json.NewEncoder(w).Encode(map[string]string{
                "error": "Insufficient permissions",
            })
            return
        }
        
        next(w, r)
    })
}

// 权限检查函数
func hasPermission(userRole, requiredRole string) bool {
    // 简单的角色层级检查
    roleHierarchy := map[string]int{
        "admin":  3,
        "editor": 2,
        "viewer": 1,
    }
    
    return roleHierarchy[userRole] >= roleHierarchy[requiredRole]
}

// 检查具体权限
func checkPermission(role, permission string) bool {
    permissions, exists := rolePermissions[role]
    if !exists {
        return false
    }
    
    for _, p := range permissions {
        if p == permission {
            return true
        }
    }
    return false
}

// 受保护的路由处理器
func protectedHandler(w http.ResponseWriter, r *http.Request) {
    json.NewEncoder(w).Encode(map[string]string{
        "message": "This is a protected endpoint",
    })
}

// 管理员路由处理器
func adminHandler(w http.ResponseWriter, r *http.Request) {
    json.NewEncoder(w).Encode(map[string]string{
        "message": "This is admin only endpoint",
    })
}

这个示例包含以下核心功能:

  1. 用户认证:使用bcrypt进行密码哈希和验证
  2. JWT令牌:生成和验证JSON Web Tokens
  3. 角色管理:定义admin、editor、viewer三种角色
  4. 权限控制
    • 基于角色的访问控制中间件
    • 权限层级检查
    • 具体权限验证

使用示例:

# 登录获取令牌
curl -X POST http://localhost:8080/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"admin123"}'

# 访问受保护端点
curl -H "Authorization: <your_token>" http://localhost:8080/protected

# 访问管理员端点(只有admin角色可以访问)
curl -H "Authorization: <your_token>" http://localhost:8080/admin-only

要扩展此系统,可以添加数据库集成、更细粒度的权限控制、角色管理API等功能。

回到顶部