中间件使用.md 3.3 KB

中间件使用

概要

jwt携带用户id信息 jwt 用户信息与header用户信息校验

修改jwt token生成逻辑

编辑loginlogic.go,将getJwtToken方法中添加userId参数,并将其添加到jwt token生成逻辑中,变更内容如下

getJwtToken方法

func (l *LoginLogic) getJwtToken(secretKey string, iat, seconds, userId int64) (string, error) {
	...
	claims["userId"] = userId 
	...
}

Login方法

func (l *LoginLogic) Login(req types.LoginReq) (*types.UserReply, error) {
	...
		jwtToken, err := l.getJwtToken(l.svcCtx.Config.Auth.AccessSecret, now, accessExpire, userInfo.Id)
    ...
}

添加中间件

添加middleware文件夹,并新建usercheckmiddleware.go

$ cd book/user/api/internal
$ mkdir middleware && cd middleware
$ touch usercheckmiddleware.go

修改user.api文件

/user/info路由所在service上添加middleware标识,然后重新生成代码

...

@server(
	jwt: Auth
	middleware: UserCheck
)
service user-api {
	@handler userInfo
	get /user/info () returns (UserReply)
}

填充ServiceContext

$ vi ~/book/user/api/internal/svc/servicecontext.go
package svc

import (
	"book/user/api/internal/config"
	"book/user/api/internal/middleware"
	"book/user/model"

	"github.com/tal-tech/go-zero/core/stores/sqlx"
	"github.com/tal-tech/go-zero/rest"
)

type ServiceContext struct {
	Config    config.Config
	UserModel model.UserModel
	UserCheck rest.Middleware
}

func NewServiceContext(c config.Config) *ServiceContext {
	conn := sqlx.NewMysql(c.Mysql.DataSource)
	um := model.NewUserModel(conn)
	return &ServiceContext{
		Config:    c,
		UserModel: um,
		UserCheck: middleware.NewUserCheckMiddleware().Handle,
	}
}

填充中间件逻辑

usercheckmiddleware.go

package middleware

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"

	"github.com/tal-tech/go-zero/rest/httpx"
)

var (
	errorUserInfo = errors.New("用户信息获取失败")
	authDeny      = errors.New("用户信息不一致")
)

const userKey = `x-user-id`

type UserCheckMiddleware struct {
}

func NewUserCheckMiddleware() *UserCheckMiddleware {
	return &UserCheckMiddleware{}
}

func (m *UserCheckMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		userId := r.Header.Get(userKey)
		jwtUserId := r.Context().Value("userId")
		userInt, err := json.Number(userId).Int64()
		if err != nil {
			httpx.Error(w, errorUserInfo)
			return
		}

		jwtInt, err := json.Number(fmt.Sprintf("%v", jwtUserId)).Int64()
		if err != nil {
			httpx.Error(w, errorUserInfo)
			return
		}

		if jwtInt != userInt {
			httpx.Error(w, authDeny)
			return
		}

		next(w, r)
	}
}

验证

$ curl -X GET \
  http://127.0.0.1:8888/user/info \
  -H 'authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDM2NDA5NTMsImlhdCI6MTYwMzU1NDU1MywidXNlcklkIjoxfQ.clyoXd7_5AJLJ_y41Wc8g9nmzvmO2qPYu_JIODK_RAQ' \
  -H 'x-user-id: 2'

user-auth-failed.png