В этой статье будет использоваться jwt-go[1] пакет для завершения интерфейса входа в систему, выпущенный token
жетон и писать jwt пара промежуточного программного обеспечения token
Единая аутентификация, чтобы избежать различных controller
Повторить запись логики аутентификации
go get -u github.com/dgrijalva/jwt-go
Новый config/jwt.go
Документ, писать Конфигурация
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
свойство
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
Добавьте соответствующую конфигурацию
jwt:
secret: 3Bde3BGEbYqtqyEUzW3ry8jKFcaPH17fRmTmqE7MDr05Lwj95uruRKrrkb44TJ4s
jwt_ttl: 43200
Новый app/services/jwt.go
Документ, писать
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
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
структура валидатора
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()
Логика входа
// 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
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
в,добавитьмаршрутизация
router.POST("/auth/login", app.Login)
использовать Apifox
Позвоните по адресу http://localhost:8888/api/auth/login. , как показано ниже, успешно возвращается Token
,Авторизоватьсяуспех
существовать global/error.go
в, определение TokenError
ошибка
type CustomErrors struct {
// ...
TokenError CustomError
}
var Errors = CustomErrors{
// ...
TokenError: CustomError{40100, "Срок авторизации истек"},
}
существовать app/common/response/response.go
середина,писать TokenFail()
, используется для token Ошибка аутентификации возвращается равномерно
func TokenFail(c *gin.Context) {
FailByError(c, global.Errors.TokenError)
}
Новый app/middleware/jwt.go
Документ, писать
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)
}
}
существовать routes/api.go
середина,использовать JWTAuth
промежуточное программное обеспечение, так что клиенту необходимо использовать правильное Token
чтобы получить доступсуществовать authRouter
Маршрутизация по группе
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
середина,писать
// 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 для получения информации о пользователе
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