这是我参与「第五届青训营」笔记创作活动的第6天
大项目基础架构图
今天完成了api+user部分的3个功能,分别是用户注册、用户登录、用户信息获取。并且使用了docker环境和cmd+dal+idl+kitex_gen+pkg的项目架构模式,以下对几个重难点作记录说明:
1. Kitex的router文件夹修改
user部分的3个功能,并不都需要用户携带token进行认证。用户注册和用户登录功能不需要携带token,而用户信息获取需要携带功能。因此,在将jwt用作路由中间件时,需要将这两类功能的路由中间件分开设置,如下:
并给用户信息获取功能添加jwt路由中间件:
这样就能实现,当客户端向/douyin/user接口发送GET请求时,jwt中间件会自动获取传入的token值并做验证。只有验证token有效,才会进行后续操作;反之,直接返回token失效。
2. 对app.RequestContext携带内容进行添加和获取
因为用户登录后需要返回token和user_id,而在Hertz的jwt中间件的LoginHandle函数中,只能自主实现LoginResponse函数,这其中就无法获取到user_id。因此,我在Authenticator函数中将调用rpc服务获得的user_id值直接存储在了c *app.RequestContext中。这样一来,自主实现的LoginResponse函数就可以从app.RequestContext中Get到user_id,从而返回到客户端。
Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) {
var err error
var req api.DouyinUserLoginRequest
if err = c.BindAndValidate(&req); err != nil {
return "", jwt.ErrMissingLoginValues
}
if len(req.Username) == 0 || len(req.Password) == 0 {
return "", jwt.ErrMissingLoginValues
}
user_id, err := rpc.CheckUser(context.Background(), &user.CheckUserRequest{
Username: req.Username,
Password: req.Password,
})
c.Set("user_id", user_id)
return user_id, err
},
LoginResponse: func(ctx context.Context, c *app.RequestContext, code int, token string, expire time.Time) {
user_id, _ := c.Get("user_id")
c.JSON(http.StatusOK, utils.H{
"status_code": errno.Success.ErrCode,
"status_msg": errno.Success.ErrMsg,
"user_id": user_id,
"token": token,
// "expire": expire.Format(time.RFC3339),
})
},
3. 功能实现展示
(1) 用户登录功能
(2) 用户注册功能
(3) 用户信息获取功能