Skip to content

认证中间件 原创

现在我们开发完了用户管理模块,改模块是需要用户登录认证过后才有操作权限。

为此,需要专门开发一个中间件来做鉴权,避免为每个接口都配置权限。

1、开发中间件

internal/app/middlewares 中新增 auth.go 文件,写入以下内容:

go
package middlewares

import (
	"github.com/gin-gonic/gin"
	"github.com/joker-bai/kubemana/internal/app/models"
	"github.com/joker-bai/kubemana/pkg/app"
	"github.com/joker-bai/kubemana/pkg/errorcode"
	"github.com/joker-bai/kubemana/pkg/jwt"
)

// Auth 认证中间件
func AuthJWT() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		// 从标头 Authorization:Bearer xxxxx 中获取信息,并验证 JWT 的准确性
		claims, err := jwt.NewJWT().ParserToken(ctx)
		response := app.NewResponse(ctx)

		// JWT 解析失败,有错误发生
		if err != nil {
			response.ToErrorResponse(errorcode.UnauthorizedTokenError)
			return
		}

		// JWT 解析成功,设置用户信息

		users := models.User{}
		userModel := users.GetUserByID(claims.UserID)
		if userModel.ID == 0 {
			response.ToErrorResponse(errorcode.UnauthorizedTokenError)
			return
		}

		// 将用户信息存入 gin.context 里,后续 auth 包将从这里拿到当前用户数据
		ctx.Set("current_user_id", userModel.GetStringID())
		ctx.Set("current_user_name", userModel.Username)
		ctx.Set("current_user", userModel)

		ctx.Next()
	}
}

首先从请求头里获取 Token 认证信息,然后解析 Token,如果解析失败则认证失败,解析成功再到数据库中判断用户是否真的存在,只有存在了才认证通过。

上面使用到 users.GetUserByID() 方法,为此,我们需要在 internal/app/models/user.go 中增加如下方法:

go
// 通过ID查找用户
func (u *User) GetUserByID(id string) User {
	var user = &User{}
	global.DB.Where("id", id).First(&user)
	return *user
}

2、修改路由

现在我们修改一下路由,把用户管理加入权限校验,修改 initialize/router.go 文件,如下:

go
package initialize

import (
	"github.com/gin-gonic/gin"
	_ "github.com/joker-bai/kubemana/docs"
	"github.com/joker-bai/kubemana/internal/app/middlewares"
	"github.com/joker-bai/kubemana/internal/app/routers"
	swaggerFiles "github.com/swaggo/files"
	ginSwagger "github.com/swaggo/gin-swagger"
)

type injector interface {
	Inject(router *gin.RouterGroup)
}

func (s *Engine) injectRouterGroup(router *gin.RouterGroup) {

	// public
	for _, r := range []injector{
		new(routers.AuthRouter),
	} {
		r.Inject(router.Group("/api/v1"))
	}

	// auth
	for _, r := range []injector{
		new(routers.UserRouter),
	} {
		r.Inject(router.Group("/api/v1", middlewares.AuthJWT()))
	}

	for _, r := range []injector{
		new(routers.HelloWorldRouter),
	} {
		r.Inject(router.Group("/api"))
	}

	router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
}

我们在路由组里加了 middlewares.AuthJWT() 表示只有这个组需要使用这个中间件,如果要加在全局,就在 initialize/server.go 中配置。

3、测试一下

(1)先不填写 token,直接测试获取用户列表,输出如下:

850a965ddaedd769fce679c6bf1d1402 MD5

给我们报服务器内部错误,从日志来看实则是权限校验未通过,如下:

go
"error":"invalid WriteHeader code 100005"

(2)添加 token 进行测试

在通过用户登录获取 token,如下:

fe6955992bd869cd42299fb6f7c2c264 MD5

然后将 token 加入到列出用户的接口中,如下:

5cc496be06c276fcb63f54f1bf47bf5e MD5

现在再执行接口,就能正常获取到用户信息了,如下:

88377839d247c135bbe660e515005794 MD5

4、代码标记

开发完本节内容,记得给代码标记一下:

go
$ git add .
$ git commit -m "新增认证中间件"
最近更新