快速开始api开发(四)登录与认证

本文需要介绍 gotools 工具

需要使用的工具命令:gotools handler -h
代码地址:github.com/wuyan94zl/gotools

登录

生成

执行:gotools handler --dir users --method POST --name login

路由 POST /users/login

设置登录出入参

修改:app/types/users.go

type UsersLoginRequest struct {
    LoginID  string `json:"login_id" validate:"required,gte=6,lte=32" tip:"用户登录名长度介于6-32位"`
    Password string `json:"password" validate:"required,gte=6,lte=32" tip:"用户密码长度介于6-32位"`
}

type UsersLoginResponse struct {
    ExpTime interface{} `json:"exp_time"` // 增加代码
    Token   interface{} `json:"token"`    // 增加代码
}

编写登录逻辑

修改:app/logic/users/login.go

package users

import (
    "errors"
    "github.com/gin-gonic/gin"
    "github.com/wuyan94zl/example-api/container"
    "github.com/wuyan94zl/example-api/app/types"
    "github.com/wuyan94zl/gotools/jwt"
    "github.com/wuyan94zl/gotools/utils"
)

func LoginLogic(c *gin.Context, req *types.UsersLoginRequest) (*types.UsersLoginResponse, error) {
    info, err := container.Instance().UserModel.FindByLoginID(c.Copy(), req.LoginID)
    if err != nil {
        return nil, errors.New("用户不存在")
    }

    if info.Password != utils.Md5ByString(req.Password+info.LoginID) {
        return nil, errors.New("密码错误")
    }

    data := make(map[string]interface{})
    data["ID"] = info.ID
    data["Nickname"] = info.Nickname
    token, err := jwt.GenToken(container.Instance().Jwt, data)
    if err != nil {
        return nil, err
    }
    return &types.UsersLoginResponse{
        ExpTime: token["expTime"],
        Token:   token["token"],
    }, nil
}

认证

生成

执行 gotools handler --dir auth --method GET --name info

路由 GET /auth/info

认证中间件

创建:app/middleware/auth.go

package middleware

import (
    "github.com/gin-gonic/gin"
    "github.com/wuyan94zl/example-api/container"
    "github.com/wuyan94zl/gotools/jwt"
)

func ApiAuth() gin.HandlerFunc {
    return func(c *gin.Context) {
        tokenString := c.Request.Header.Get("Authorization")
        token, err := jwt.AuthBearerToken(container.Instance().Jwt, tokenString)
        if err != nil {
            c.JSON(401, err)
            c.Abort()
        }
        data := token["Data"].(map[string]interface{})
        for k, v := range data {
            c.Set(k, v)
        }
        // 保存用户到 上下文
        c.Next()
    }
}

路由

修改 router/route.go

package router

import (
    "github.com/gin-gonic/gin"
    "github.com/wuyan94zl/example-api/app/middleware"
)

func RegisterHandlers(app *gin.RouterGroup) {
    registerUsersHandler(app)
    authApp := app.Group("", middleware.ApiAuth()) // 增加认证路由组
    registerAuthHandler(authApp)// 修改传参
}

入参出参设置

package types

type AuthInfoRequest struct{}

type AuthInfoResponse struct {
    ID       int    `json:"id"`
    Nickname string `json:"nickname"`
    HeadImg  string `json:"head_img"`
}

逻辑编写

package auth

import (
    "github.com/gin-gonic/gin"
    "github.com/wuyan94zl/example-api/container"

    "github.com/wuyan94zl/example-api/app/types"
)

func InfoLogic(c *gin.Context, req *types.AuthInfoRequest) (*types.AuthInfoResponse, error) {
    id := c.MustGet("ID").(float64)
    info, err := container.Instance().UserModel.First(c.Copy(), int64(id))
    if err != nil {
        return nil, err
    }
    return &types.AuthInfoResponse{
        ID:       info.ID,
        Nickname: info.Nickname,
        HeadImg:  info.HeadImg,
    }, nil
}

结束

下节 定时任务 crontab 和 队列 queue (划重点)

本作品采用《CC 协议》,转载必须注明作者和本文链接
没有造飞机的格局,怎么能拧得好螺丝。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!