登录后端部分主要是通过jwt鉴权,首先验证用户名和密码再返回token值给前端即可
由于go-zero自己已经继承了jwt鉴权,所以可以直接使用
package logic
// 用户服务层实例
type UserLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
// 返回用户服务层实例
func NewUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserLogic {
return &UserLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
// getToken 获取token值
func (u *UserLogic) getToken(iat int64, secretKey string, payloads map[string]interface{}, seconds int64) (string, error) {
claims := make(jwt.MapClaims)
claims["exp"] = iat + seconds
claims["iat"] = iat
for k, v := range payloads {
claims[k] = v
}
token := jwt.New(jwt.SigningMethodHS256)
token.Claims = claims
return token.SignedString([]byte(secretKey))
}
package types
type (
UserInfoReq struct {
UserID int64 `json:"user_id" validate:"required" message:"请输入用户id"`
}
// LoginReq 用户登录请求数据
LoginReq struct {
UserName string `json:"user_name" validate:"required, max=32" message:"请输入用户名,用户名不超过32个字符"` // 用户名
Password string `json:"password" validate:"required, max=32" message:"请输入用户密码,密码不超过32个字符"` // 用户密码
}
// LoginResp 用户登录返回数据
LoginResp struct {
Token string `form:"token"` // 用户token值
}
)
// Info 获取用户信息
func (u *UserLogic) Info(req types.UserInfoReq) (resp models.User, err error) {
// 根据token获取用户相关信息:u.ctx.Value()
err = u.svcCtx.Mysql.Model(models.User{}).Where("id=?", u.ctx.Value("uid")).First(&resp).Error
return
}
// Login 用户登录
func (u *UserLogic) Login(req types.LoginReq) (resp *types.LoginResp, err error) {
var userInfo models.User
resp = new(types.LoginResp)
// 验证数据库是否有该用户
if err = u.svcCtx.Mysql.Model(models.User{}).Where("user_name=? and status=1", req.UserName).First(&userInfo).Error; err != nil {
return
}
if userInfo.Password != req.Password {
err = errors.New("密码错误")
return
}
resp.Token, err = u.getToken(time.Now().Unix(), u.svcCtx.Config.Auth.AccessSecret, map[string]interface{}{"uid": 1, "username": "root"}, u.svcCtx.Config.Auth.AccessExpire)
return
}
package handler
import (
"app/auth/api/internal/logic"
"app/auth/api/internal/svc"
"app/auth/api/internal/types"
"app/models"
"app/tools/response"
"github.com/zeromicro/go-zero/rest/httpx"
"net/http"
)
func UserInfoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var (
req types.UserInfoReq
err error
resp models.User
)
if err = httpx.Parse(r, &req); err != nil {
response.Json(w, err.Error(), response.Fail)
return
}
if resp, err = logic.NewUserLogic(r.Context(), svcCtx).Info(req); err != nil {
response.Json(w, err.Error(), response.Fail)
return
}
response.Json(w, resp)
}
}
func LoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var (
req types.LoginReq
resp *types.LoginResp
err error
)
if err = httpx.Parse(r, &req); err != nil {
response.Json(w, err.Error(), response.Fail)
return
}
if resp, err = logic.NewUserLogic(r.Context(), svcCtx).Login(req); err != nil {
response.Json(w, err.Error(), response.InvalidParams)
return
}
response.Json(w, resp)
}
}
package handler
import (
"app/auth/api/internal/svc"
"net/http"
"github.com/zeromicro/go-zero/rest"
)
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodPost,
Path: "/auth/user/login",
Handler: LoginHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/auth/user/info",
Handler: UserInfoHandler(serverCtx),
},
},
)
}
这样后端部分的接口就开发完成了,总结以下后端开发流程:
1. internal/types[声明接口请求/响应结构体]
2. internal/logic[服务层接口开发]
3. internal/handler[控制层接口开发]
4. internal/types[声明接口请求/响应结构体]
启动服务
go run .\auth.go -f .\etc\auth-api.yaml