Шаг за шагом я покажу вам инкапсуляцию инфраструктуры Gin с нуля (7): Реализуйте интерфейс входа в систему. & jwt Промежуточное программное обеспечение аутентификации
Шаг за шагом я покажу вам инкапсуляцию инфраструктуры Gin с нуля (7): Реализуйте интерфейс входа в систему. & jwt Промежуточное программное обеспечение аутентификации

Предисловие

В этой статье будет использоваться jwt-go[1] пакет для завершения интерфейса входа в систему, выпущенный token жетон и писать jwt пара промежуточного программного обеспечения token Единая аутентификация, чтобы избежать различных controller Повторить запись логики аутентификации

Установить

Язык кода:javascript
копировать
go get -u github.com/dgrijalva/jwt-go

Определить элементы конфигурации

Новый config/jwt.go Документ, писать Конфигурация

Язык кода:javascript
копировать
package config

type Jwt struct {
    Secret string `mapstructure:"secret" json:"secret" yaml:"secret"`
    JwtTtl int64 `mapstructure:"jwt_ttl" json:"jwt_ttl" yaml:"jwt_ttl"` // token Срок действия (секунды)
}

существовать config/config.go в, добавить Jwt свойство

Язык кода:javascript
копировать
package config

type Configuration struct {
    App App `mapstructure:"app" json:"app" yaml:"app"`
    Log Log `mapstructure:"log" json:"log" yaml:"log"`
    Database Database `mapstructure:"database" json:"database" yaml:"database"`
    Jwt Jwt `mapstructure:"jwt" json:"jwt" yaml:"jwt"`
}

config.yaml Добавьте соответствующую конфигурацию

Язык кода:javascript
копировать
jwt:
  secret: 3Bde3BGEbYqtqyEUzW3ry8jKFcaPH17fRmTmqE7MDr05Lwj95uruRKrrkb44TJ4s
  jwt_ttl: 43200

Написать логику выдачи токенов

Новый app/services/jwt.go Документ, писать

Язык кода:javascript
копировать
package services

import (
    "github.com/dgrijalva/jwt-go"
    "jassue-gin/global"
    "time"
)

type jwtService struct {
}

var JwtService = new(jwtService)

// Все, что тебе нужно, проблема token Модель пользователя должна реализовать этот интерфейс.
type JwtUser interface {
    GetUid() string
}

// CustomClaims Настроить Claims
type CustomClaims struct {
    jwt.StandardClaims
}

const (
    TokenType = "bearer"
    AppGuardName = "app"
)

type TokenOutPut struct {
    AccessToken string `json:"access_token"`
    ExpiresIn int `json:"expires_in"`
    TokenType string `json:"token_type"`
}

// CreateToken генерировать Token
func (jwtService *jwtService) CreateToken(GuardName string, user JwtUser) (tokenData TokenOutPut, err error, token *jwt.Token) {
    token = jwt.NewWithClaims(
        jwt.SigningMethodHS256,
        CustomClaims{
            StandardClaims: jwt.StandardClaims{
                ExpiresAt: time.Now().Unix() + global.App.Config.Jwt.JwtTtl,
                Id:        user.GetUid(),
                Issuer:    GuardName, // используется длясуществоватьпромежуточное программное программное обеспечение различает разные клиенты жетон, избегай token Перекрестныйиспользовать                NotBefore: time.Now().Unix() - 1000,
            },
        },
    )

    tokenStr, err := token.SignedString([]byte(global.App.Config.Jwt.Secret))

    tokenData = TokenOutPut{
        tokenStr,
        int(global.App.Config.Jwt.JwtTtl),
        TokenType,
    }
    return
}

CreateToken Метод должен получить JwtUser экземпляр объекта, нам нужно app/models/user.go Реализация пользовательской модели JwtUser интерфейс, Последующие другие пользовательские модели могут быть реализованы через JwtUser интерфейс, позвонить CreateToken() проблема Token

Язык кода:javascript
копировать
package models

import "strconv"

type User struct {
    ID
    Name string `json:"name" gorm:"not null;комментарий:имя пользователя"`
    Mobile string `json:"mobile" gorm:"not null;индекс;комментарий:номер мобильного телефона пользователя"`
    Password string `json:"-" gorm:"not null;default:'';комментарий:пароль пользователя"`
    Timestamps
    SoftDeletes
}

func (user User) GetUid() string {
    return strconv.Itoa(int(user.ID.ID))
}

Реализовать интерфейс входа в систему

существовать app/common/request/user.go Средний, новый Login структура валидатора

Язык кода:javascript
копировать
type Login struct {
    Mobile string `form:"mobile" json:"mobile" binding:"required,mobile"`
    Password string `form:"password" json:"password" binding:"required"`
}

func (login Login) GetMessages() ValidatorMessages {
    return ValidatorMessages{
        "mobile.required": «Номер мобильного телефона не может быть пустым»,
        "mobile.mobile": «Неверный формат номера мобильного телефона»,
        "password.required": "Пароль пользователя не может быть пустым",
    }
}

существовать app/services/user.go середина,писать Login() Логика входа

Язык кода:javascript
копировать
// Login Авторизоваться
func (userService *userService) Login(params request.Login) (err error, user *models.User) {
    err = global.App.DB.Where("mobile = ?", params.Mobile).First(&user).Error
    if err != nil || !utils.BcryptMakeCheck([]byte(params.Password), user.Password) {
        err = error.New("Имя пользователя не существует или пароль ошибочный")
    }
    return
}

Новый app/controllers/app/auth.go Документ, писать Login() Выполните проверку входных параметров и вызовите UserService и JwtService Служить,проблема Token

Язык кода:javascript
копировать
package app

import (
    "github.com/gin-gonic/gin"
    "jassue-gin/app/common/request"
    "jassue-gin/app/common/response"
    "jassue-gin/app/services"
)

func Login(c *gin.Context) {
    var form request.Login
    if err := c.ShouldBindJSON(&form); err != nil {
        response.ValidateFail(c, request.GetErrorMsg(form, err))
        return
    }

    if err, user := services.UserService.Login(form); err != nil {
        response.BusinessFail(c, err.Error())
    } else {
        tokenData, err, _ := services.JwtService.CreateToken(services.AppGuardName, user)
        if err != nil {
            response.BusinessFail(c, err.Error())
            return
        }
        response.Success(c, tokenData)
    }
}

существовать routes/api.go в,добавитьмаршрутизация

Язык кода:javascript
копировать
router.POST("/auth/login", app.Login)

использовать Apifox Позвоните по адресу http://localhost:8888/api/auth/login. , как показано ниже, успешно возвращается Token,Авторизоватьсяуспех

писать jwt Промежуточное программное обеспечение аутентификации

существовать global/error.go в, определение TokenError ошибка

Язык кода:javascript
копировать
type CustomErrors struct {
    // ...
    TokenError CustomError
}

var Errors = CustomErrors{
    // ...
    TokenError: CustomError{40100, "Срок авторизации истек"},
}

существовать app/common/response/response.go середина,писать TokenFail() , используется для token Ошибка аутентификации возвращается равномерно

Язык кода:javascript
копировать
func TokenFail(c *gin.Context) {
    FailByError(c, global.Errors.TokenError)
}

Новый app/middleware/jwt.go Документ, писать

Язык кода:javascript
копировать
package middleware

import (
    "github.com/dgrijalva/jwt-go"
    "github.com/gin-gonic/gin"
    "jassue-gin/app/common/response"
    "jassue-gin/app/services"
    "jassue-gin/global"
)

func JWTAuth(GuardName string) gin.HandlerFunc {
    return func(c *gin.Context) {
        tokenStr := c.Request.Header.Get("Authorization")
        if tokenStr == "" {
            response.TokenFail(c)
            c.Abort()
            return
        }
        tokenStr = tokenStr[len(services.TokenType)+1:]

        // Token Разбор и проверка
        token, err := jwt.ParseWithClaims(tokenStr, &services.CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
            return []byte(global.App.Config.Jwt.Secret), nil
        })
        if err != nil {
            response.TokenFail(c)
            c.Abort()
            return
        }

        claims := token.Claims.(*services.CustomClaims)
        // Token Проверка издателя
        if claims.Issuer != GuardName {
            response.TokenFail(c)
            c.Abort()
            return
        }

        c.Set("token", token)
        c.Set("id", claims.Id)
    }
}

Используйте промежуточное программное обеспечение jwt для реализации интерфейса получения информации о пользователе.

существовать routes/api.go середина,использовать JWTAuth промежуточное программное обеспечение, так что клиенту необходимо использовать правильное Token чтобы получить доступсуществовать authRouter Маршрутизация по группе

Язык кода:javascript
копировать
func SetApiGroupRoutes(router *gin.RouterGroup) {
    router.POST("/auth/register", app.Register)
    router.POST("/auth/login", app.Login)

    authRouter := router.Group("").Use(middleware.JWTAuth(services.AppGuardName))
    {
        authRouter.POST("/auth/info", app.Info)
    }
}

существовать app/services/user.go середина,писать

Язык кода:javascript
копировать
// GetUserInfo Получить информацию о пользователе
func (userService *userService) GetUserInfo(id string) (err error, user models.User) {
    intId, err := strconv.Atoi(id)
    err = global.App.DB.First(&user, intId).Error
    if err != nil {
        err = errors.New("Данные не существуютсуществовать")    }
    return
}

существовать app/controllers/auth.goсередина,писать Info(),проходить JWTAuth Проверка промежуточного программного обеспечения Token идентифицированный пользователь ID для получения информации о пользователе

Язык кода:javascript
копировать
func Info(c *gin.Context) {
    err, user := services.UserService.GetUserInfo(c.Keys["id"].(string))
    if err != nil {
        response.BusinessFail(c, err.Error())
        return
    }
    response.Success(c, user)
}

использовать Apifox,Первый звонок Авторизоваться, чтобы получить Token вставить Authorization заголовок, а затем вызвать интерфейс http://localhost:8888/api/auth/info

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose