Статья была впервые опубликована в Личном блогеISLANDи личный универсальный аккаунтОхотник за кодом
В проектах с разделением фронтенда и бэкенда все больше и больше проектов внедряютJWT
заменить традиционныеcookie
, здесь мы используемJWT
комбинироватьGin
В качестве авторизации входа и проверки разрешений.
🔑Что такое JWT
Полное название JWT называется JSON WEB TOKEN, которое широко используется в текущих интерфейсных и серверных системах.
Состав JWT
JWT состоит из трех сегментов. Это HEADER, PAYLOAD, VERIFY SIGNATURE, и информация, которую они генерируют, передается через.
сегментация.
HEADER
заголовок состоит изtyp
иalg
сочинение,typ
будет указан как JWT, иalg
используется алгоритм шифрования.
{
"alg": "HS256",
"typ": "JWT"
}
PAYLOAD
Полезная нагрузка является носителем JWT, то есть информации, которую мы хотим нести. Эту часть информации можно настроить, и мы можем определить, какую информацию мы хотим хранить, эти поля. Эта часть информации не должна быть слишком большой, это повлияет на размер генерации JWT, и не храните конфиденциальные данные в этой части, внешний интерфейс данных может анализировать и получать информацию в токене.
Официальный дал семь полей по умолчанию, мы не можем использовать их все, или мы можем добавить нужные нам поля.
название | значение |
---|---|
Audience | Представляет аудиторию JWT |
ExpiresAt | время отказа |
Id | Номер выпуска |
IssuedAt | Время выпуска |
Issuer | подписывающий |
NotBefore | эффективное время |
Subject | тема |
VERIFY SIGNATURE
Это также последний пункт JWT, который рассчитывается алгоритмом.
Выполните кодировку base64Url для заголовка прямо сейчас, кодировку base64Url для полезной нагрузки и передайте кодировку после кодирования обоих концов..
подключить.
base64UrlEncode(header).base64UrlEncode(payload)
После выполнения вышеуказанных шагов нам нужно зашифровать верхнюю часть с помощью алгоритма шифрования, указанного в нашем заголовке, а также нам нужно вставить один из наших ключей, чтобы убедиться, что моя выдача JWT безопасна.
Это наша третья часть.
Когда все три части готовы, с помощью.
Три части разделены на генерацию JWT, показанного на рисунке выше.
Принцип входа в JWT
Проще говоря, когда пользователь входит в систему, сервер проверяет правильность имени пользователя и пароля.Если они верны, JWT будет сгенерирован и возвращен клиенту. После того, как клиент получит JWT, его необходимо сохранить. В каждом последующем запросе будет указано, что JWT переносится в заголовке. Каждый раз сервер будет получать информацию о том, правильный ли JWT в заголовке. Если он правильный, запрос будет выполняться корректно. Если верификация не удалась, авторизуйтесь снова.
🔒Гин Создать JWT
Для языка go существует множество библиотек JWT.jwt.ioМногие также приведены выше. использовать здесьjwt-go
"github.com/dgrijalva/jwt-go"
Мы переработали метод входа.
// 省略代码
expiresTime := time.Now().Unix() + int64(config.OneDayOfHours)
claims := jwt.StandardClaims{
Audience: user.Username, // 受众
ExpiresAt: expiresTime, // 失效时间
Id: string(user.ID), // 编号
IssuedAt: time.Now().Unix(), // 签发时间
Issuer: "gin hello", // 签发人
NotBefore: time.Now().Unix(), // 生效时间
Subject: "login", // 主题
}
var jwtSecret = []byte(config.Secret)
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// 省略代码
здесьconfig.OneDayOfHours
设定了过期时间,这里设定了一天。 пройти черезStandardClaims
Сгенерируйте стандартный носитель, то есть семь полей, упомянутых выше, где число установлено для идентификатора пользователя. один из нихjwtSecret
Ключ, который мы установили,
Здесь мы генерируем его через алгоритм HS256.tokenClaims
, это наш раздел HEADER и PAYLOAD.
token, err := tokenClaims.SignedString(jwtSecret)
Это генерирует наш токен. Мы собираемся соединить наш токен и Bearer вместе, разделив их пробелами.
token = "Bearer "+ token
Сгенерируйте токен носителя.
Когда наш пользователь входит в систему, мы можем генерировать JWT через этот фрагмент.
Вот полный код:
func CreateJwt(ctx *gin.Context) {
// 获取用户
user := &model.User{}
result := &model.Result{
Code: 200,
Message: "登录成功",
Data: nil,
}
if e := ctx.BindJSON(&user); e != nil {
result.Message = "数据绑定失败"
result.Code = http.StatusUnauthorized
ctx.JSON(http.StatusUnauthorized, gin.H{
"result": result,
})
}
u := user.QueryByUsername()
if u.Password == user.Password {
expiresTime := time.Now().Unix() + int64(config.OneDayOfHours)
claims := jwt.StandardClaims{
Audience: user.Username, // 受众
ExpiresAt: expiresTime, // 失效时间
Id: string(user.ID), // 编号
IssuedAt: time.Now().Unix(), // 签发时间
Issuer: "gin hello", // 签发人
NotBefore: time.Now().Unix(), // 生效时间
Subject: "login", // 主题
}
var jwtSecret = []byte(config.Secret)
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
if token, err := tokenClaims.SignedString(jwtSecret); err == nil {
result.Message = "登录成功"
result.Data = "Bearer " + token
result.Code = http.StatusOK
ctx.JSON(result.Code, gin.H{
"result": result,
})
} else {
result.Message = "登录失败"
result.Code = http.StatusOK
ctx.JSON(result.Code, gin.H{
"result": result,
})
}
} else {
result.Message = "登录失败"
result.Code = http.StatusOK
ctx.JSON(result.Code, gin.H{
"result": result,
})
}
}
Через тест запроса .http результаты следующие:
{
"result": {
"code": 200,
"message": "登录成功",
"data": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIxMjMiLCJleHAiOjE1NjQ3OTY0MzksImp0aSI6Ilx1MDAwMCIsImlhdCI6MTU2NDc5NjQxOSwiaXNzIjoiZ2luIGhlbGxvIiwibmJmIjoxNTY0Nzk2NDE5LCJzdWIiOiJsb2dpbiJ9.CpacmfBSMgmK2TgrT-KwNB60bsvwgyryGQ0pWZr8laU"
}
}
На этом генерация токена завершена.
🔐Жетон чека на джин
Затем следующим шагом будет завершение проверки токена.
Помните, как мы проверяем, что пользователь авторизован? Да, проверьте пользователя cookie в промежуточном программе. Тот же метод, мы проверяем, действителен ли пользователь JWT здесь.
Напишите нашу промежуточное программное обеспечение.
Вновь установленоmiddleware/Auth.go
Сначала напишите наш метод разборки токена,parseToken()
func parseToken(token string) (*jwt.StandardClaims, error) {
jwtToken, err := jwt.ParseWithClaims(token, &jwt.StandardClaims{}, func(token *jwt.Token) (i interface{}, e error) {
return []byte(config.Secret), nil
})
if err == nil && jwtToken != nil {
if claim, ok := jwtToken.Claims.(*jwt.StandardClaims); ok && jwtToken.Valid {
return claim, nil
}
}
return nil, err
}
Токен анализируется входящим нашим токеном.
Полный промежуточный код
func Auth() gin.HandlerFunc {
return func(context *gin.Context) {
result := model.Result{
Code: http.StatusUnauthorized,
Message: "无法认证,重新登录",
Data: nil,
}
auth := context.Request.Header.Get("Authorization")
if len(auth) == 0 {
context.Abort()
context.JSON(http.StatusUnauthorized, gin.H{
"result": result,
})
}
auth = strings.Fields(auth)[1]
// 校验token
_, err := parseToken(auth)
if err != nil {
context.Abort()
result.Message = "token 过期" + err.Error()
context.JSON(http.StatusUnauthorized, gin.H{
"result": result,
})
} else {
println("token 正确")
}
context.Next()
}
}
Сначала получите токен в заголовке запроса, затем сначала проанализируйте токен, разделите Bearer и JWT и проверьте JWT.
Нам нужно только проверить маршрут, который нам нужно добавить промежуточное программное обеспечение для проверки.
router.GET("/", middleware.Auth(), func(context *gin.Context) {
context.JSON(http.StatusOK, time.Now().Unix())
})
когда мы посещаем/
Когда нужно носить жетон
GET http://localhost:8080
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIxMjMiLCJleHAiOjE1NjQ3OTQzNjIsImp0aSI6Ilx1MDAwMCIsImlhdCI6MTU2NDc5NDM0MiwiaXNzIjoiZ2luIGhlbGxvIiwibmJmIjoxNTY0Nzk0MzQyLCJzdWIiOiJsb2dpbiJ9.uQxGMsftyVFtYIGwQVm1QB2djw-uMfDbw81E5LMjliU
✍Резюме
В этой главе рассказывается, что такое JWT и как использовать JWT в Gin. Но не стоит слишком суеверно относиться к JWT. С JWT еще много проблем. Например, JWT можно аннулировать только по истечении времени. Если вы меняете пароль или выходите из учетной записи, нам нужно добавить дополнительную логику. Правильное место для использования правильной технологии может сыграть самое большое преимущество.
👨💻 Код для этой главы
историческая статья
Джин (1): Привет
Джин (2): маршрутизатор маршрутизации
Джин (три): шаблон tmpl
Джин (четыре): проверка отправки формы и привязка модели
Джин (5): подключиться к MySQL
Джин (шесть): загрузка файла
Джин (семь): использование и определение промежуточного программного обеспечения
Джин (8): использование файлов cookie
Джин (9): Создать спокойный интерфейс
Джин (десять): интегрированный чванство
Джин (11) интегрированный ORM-горм
Джин (12) интегрированный JWT