API Gateway
增加 Jwt
鉴权
userinfo
接口与 login
或 register
接口不同,在接口调用的时候,需要做鉴权。
编辑 api/etc
下的 user-api.yaml
文件,新增如下
yaml
Auth:
AccessSecret: ad879037-d3fd-tghj-112d-6bfc35d54b7d
AccessExpire: 86400
编辑 api/internal/config
下的 config.go
文件,新增如下
go
type Config struct {
rest.RestConf
DataSource string
AccessSecret string
AccessExpire int64
Salt string
Auth struct { // JWT 认证需要的密钥和过期时间配置
AccessSecret string
AccessExpire int64
}
}
编辑 api
下的 user.api
文件, 修改为如下
api
info(
title: "UserApi"
desc: "用户服务相关 API"
author: "DESKTOP-4T5UKHP/Owner"
email: "renpanpan1990@163.com"
)
type LoginRequest {
Email string `json:"email"`
Password string `json:"password"`
}
type LoginResponse {
UserReply
}
type RegisterRequest {
Username string `json:"username"`
Email string `json:"email"`
Password string `json:"password"`
}
type RegisterResponse {
UserReply
}
type UserinfoResponse {
UserReply
}
type UserReply {
Id int64 `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
JwtToken
}
type JwtToken {
AccessToken string `json:"accessToken,omitempty"`
AccessExpire int64 `json:"accessExpire,omitempty"`
RefreshAfter int64 `json:"refreshAfter,omitempty"`
}
service user-api {
@handler Login // 用户登录
post /users/login(LoginRequest) returns(LoginResponse)
@handler Register // 用户注册
post /users/register(RegisterRequest) returns(RegisterResponse)
}
@server (
jwt: Auth
)
service user-api {
@handler UserInfo // 用户信息
post /users/userinfo() returns(UserinfoResponse)
}
UserInfo
接口的调用需要 jwt
鉴权,于是,我们新增了
api
@server (
jwt: Auth
)
service user-api {
@handler UserInfo // 用户信息
post /users/userinfo() returns(UserinfoResponse)
}
由于原来我们生成过 user-api
服务,userinfohandle.go
和 userinfologic.go
文件不符合我们现在的需求,需要删除掉这两个文件重新生成。
重新生成 user-api
服务
bash
$ goctl api go -api user.api -dir .
查看 api/internal/handler
下的 routers.go
文件。 userinfo
接口与 login register
接口分开处理了,并且增加了 rest.WithJwt(serverCtx.Config.Auth.AccessSecret)
鉴权处理。
go
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodPost,
Path: "/users/login",
Handler: LoginHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/users/register",
Handler: RegisterHandler(serverCtx),
},
},
)
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodPost,
Path: "/users/userinfo",
Handler: UserInfoHandler(serverCtx),
},
},
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
)
}
编辑 api/internal/handler
下的 userinfohandler.go
文件,新增如下代码
go
func UserInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := logic.NewUserInfoLogic(r.Context(), svcCtx)
resp, err := l.UserInfo()
if err != nil {
// httpx.ErrorCtx(r.Context(), w, err)
httpx.OkJson(w, renpanpan.FailureResponse(nil, err.Error(), 1000))
} else {
// httpx.OkJsonCtx(r.Context(), w, resp)
httpx.OkJson(w, renpanpan.SuccessResponse(resp, "获取成功"))
}
}
}
在 api/internal/logic
下的 userinfologic.go
文件中, 修改 UserInfo
方法如下:
go
func (l *UserInfoLogic) UserInfo() (*types.UserinfoResponse, error) {
// 获取 jwt 载体中 `userId` 信息
userId, err := l.ctx.Value("userId").(json.Number).Int64()
if err != nil {
return nil, err
}
user, err := l.svcCtx.Model.FindOne(l.ctx, userId)
if err != nil {
return nil, err
}
response := types.UserReply{
Id: user.Id,
Username: user.Name,
Email: user.Email,
}
return &types.UserinfoResponse{UserReply: response}, nil
}
启动服务
启动 user api
服务, 运行成功后,user api
则运行在本机的 8888
端口
bash
➜ FoodGuides:
$ go run usermanage/api/user.go -f usermanage/api/etc/user-api.yaml
Starting server at 0.0.0.0:8888...
我们用 Postman
尝试请求用户信息接口:
- 我们先测试不携带
Authorization
的情况。其请求结果显示未授权(401 Unauthorized),如下图所示。
- 我们再测试携带
Authorization
后的情况。在Postman
的Authorization
选项中选择Bearer Token
,填写登录成功后Api
返回的accessToken
字段值。其请求结果如下图所示,说明用户信息服务运行正常。
注意:因为 jwt 载体中存在 userId
信息,所以只要 Authorization
不变,请求到的结果永远都是同一用户的信息。如果想请求其他用户信息,必须调用登录或注册接口,将返回的 accessToken
字段值设置到 Postman
的 Bearer Token
中,重新发起请求用户信息的请求。