为了构建一个安全、可扩展且易于维护的认证授权中间件,我们可以结合使用 Swagger、JWT(JSON Web Token) 和 RBAC(基于角色的访问控制)。
详细的步骤和关键实现细节,帮助你在 Go(Golang)应用程序中实现这一架构。
1.用户登录:用户通过登录接口提供凭证(如用户名和密码)。
2.生成 JWT:服务器验证凭证后,生成 JWT 并返回给客户端。
3.请求附带 JWT:客户端在后续的 API 请求中,将 JWT 包含在 Authorization
头中(如 Bearer
)。
4.中间件验证:
5.RBAC 检查:根据用户角色和请求的资源和操作,检查用户是否有权限访问。
6.处理请求:如果验证和授权通过,将请求传递给相应的处理函数;否则,返回相应的错误响应。
首先,需要引入实现 JWT 和 RBAC 所需的 Go 库。我们将使用 gin
作为 Web 框架,jwt-go
用于 JWT 处理,cors
用于跨域资源共享(可选),以及 swaggo
用于 Swagger 集成。
go
import (
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"github.com/gin-contrib/cors"
"github.com/gin-contrib/swagger"
"github.com/gin-contrib/swagger/swaggerFiles"
"net/http"
"time"
"strings"
)
定义 JWT 声明结构体和用户模型,用于存储用户信息和权限。
go
type Claims struct {
Username string `json:"username"`
Role string `json:"role"`
jwt.StandardClaims
}
type User struct {
Username string
Password string
Role string
}
配置 JWT 的签名密钥和过期时间。确保签名密钥的安全存储,可以使用环境变量或安全的密钥管理服务。
go
var jwtKey = []byte("your_secret_key")
func GenerateToken(username string, role string) (string, error) {
expirationTime := time.Now().Add(24 * time.Hour) // 令牌有效期为24小时
claims := &Claims{
Username: username,
Role: role,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expirationTime.Unix(),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(jwtKey)
}
实现一个中间件,用于验证 JWT 并提取用户信息。如果验证失败,返回 401 未授权错误。
go
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
if authHeader == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization header is missing"})
c.Abort()
return
}
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
// 确保 token 使用的是预期的签名方法
return jwtKey, nil
})
if err != nil {
if err == jwt.ErrSignatureInvalid {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token signature"})
} else {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
}
c.Abort()
return
}
if !token.Valid {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
c.Abort()
return
}
c.Set("user", claims)
c.Next()
}
}
实现一个中间件,用于根据用户角色和请求的资源和操作进行权限检查。可以根据需要扩展为更复杂的权限管理。
go
func RBACMiddleware(allowedRoles []string) gin.HandlerFunc {
return func(c *gin.Context) {
userInterface, exists := c.Get("user")
if !exists {
c.JSON(http.StatusInternalServerError, gin.H{"error": "User information is missing"})
c.Abort()
return
}
user := userInterface.(*Claims)
if !contains(allowedRoles, user.Role) {
c.JSON(http.StatusForbidden, gin.H{"error": "Forbidden"})
c.Abort()
return
}
c.Next()
}
}
func contains(slice []string, item string) bool {
for _, elem := range slice {
if elem == item {
return true
}
}
return false
}
配置 Swagger 以生成 API 文档。确保在 main.go
中添加 Swagger 相关的路由。
go
func SetupSwagger(router *gin.Engine) {
router.GET("/swagger/*any", swagger.WrapHandler(swaggerFiles.Handler, swagger.URL("http://localhost:8080/swagger/doc.json")))
}
定义 API 路由,并应用认证和 RBAC 中间件。根据需要,可以为不同的路由组应用不同的 RBAC 规则。
go
func main() {
router := gin.Default()
// 配置 CORS(根据需要配置)
router.Use(cors.Default())
// 登录接口,不需要认证
router.POST("/login", LoginHandler)
// 需要认证的路由组
auth := router.Group("/auth")
auth.Use(AuthMiddleware())
{
// 需要管理员角色的路由
admin := auth.Group("/admin")
admin.Use(RBACMiddleware([]string{"admin"}))
{
admin.GET("/dashboard", AdminDashboardHandler)
}
// 需要用户角色的路由
user := auth.Group("/user")
user.Use(RBACMiddleware([]string{"user", "admin"}))
{
user.GET("/profile", UserProfileHandler)
}
}
// 配置 Swagger
SetupSwagger(router)
router.Run(":8080")
}
实现具体的处理函数,如登录、仪表板和用户配置文件。
go
func LoginHandler(c *gin.Context) {
var userInput User
if err := c.ShouldBindJSON(&userInput); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request payload"})
return
}
// 这里应该验证用户凭证,例如查询数据库
// 假设验证通过
token, err := GenerateToken(userInput.Username, userInput.Role)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"})
return
}
c.JSON(http.StatusOK, gin.H{"token": token})
}
func AdminDashboardHandler(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Welcome to the admin dashboard"})
}
func UserProfileHandler(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"message": "Welcome to your profile"})
}
通过结合 Swagger、JWT 和 RBAC,您可以构建一个安全、可扩展且易于维护的认证授权中间件。
Swagger 提供 API 文档和交互式测试,JWT 提供安全的认证机制,而 RBAC 则根据用户角色控制对资源的访问权限。
这种设计不仅提高了应用程序的安全性,还增强了系统的灵活性和可维护性。
联系方式:https://t.me/XMOhost26
交流技术群:https://t.me/owolai007