此处所采用的乃是 Go 语言的 Gin 框架,借助中间件这一途径来达成认证与鉴权之目的。
认证
基于请求头中的 Authorization 来开展认证工作,判别 token 是否存在,token 是否合法,将 token 中的角色信息等存置于上下文中。
func AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader(Authorization)
if token == {
utils.ResponseWithError(c, http.StatusUnauthorized, 未授权)
c.Abort()
return
}
token = strings.TrimPrefix(token, Bearer )
tokenMD5, err := config.RedisClient.Get(c, token).Result()
if err != nil {
utils.ResponseWithError(c, http.StatusUnauthorized, token不存在)
c.Abort()
return
}
// 解析 token
claims, err := utils.ParseToken(tokenMD5)
if err != nil {
utils.ResponseWithError(c, http.StatusUnauthorized, 无效的 token)
c.Abort()
return
}
// 将解析后的内容存入上下文
c.Set(permissions, claims[permissions])
c.Set(userId, claims[userId])
// 继续执行
c.Next()
}
}鉴权
凭借上下文中的角色信息来实施鉴权操作
func AuthorizationMiddleware(requiredPermissions []string) gin.HandlerFunc {
return func(c *gin.Context) {
// 获取用户权限列表
permissions, exists := c.Get(permissions)
if !exists {
utils.ResponseWithError(c, http.StatusForbidden, 权限信息缺失)
c.Abort()
return
}
// 转换成 []string
userPermissions, ok := permissions.([]string)
if !ok {
utils.ResponseWithError(c, http.StatusForbidden, 权限数据格式错误)
c.Abort()
return
}
// 检查用户是否拥有所需的权限
for _, requiredPermission := range requiredPermissions {
if !contains(userPermissions, requiredPermission) {
utils.ResponseWithError(c, http.StatusForbidden, 权限不足)
c.Abort()
return
}
}
// 如果权限匹配,继续执行
c.Next()
}
}
// 检查权限列表是否包含某个权限
func contains(permissions []string, permission string) bool {
for _, p := range permissions {
if p == permission {
return true
}
}
return false
}在路由中使用
r := gin.Default()
// 认证中间件
r.Use(AuthMiddleware())
// 使用鉴权中间件
r.GET(/admin, AuthorizationMiddleware(admin), func(c *gin.Context) {
// 只有管理员才能访问这个路由
c.JSON(http.StatusOK, gin.H{message: Welcome Admin!})
})
r.GET(/user, AuthorizationMiddleware(user), func(c *gin.Context) {
// 只有普通用户才能访问这个路由
c.JSON(http.StatusOK, gin.H{message: Welcome User!})
}) 