Практика обновления токена JWT

Python

Веб-токен Json (JWT), согласно определению официального сайта, представляет собой открытый стандарт на основе JSON ((RFC 7519). Сценарии единого входа (SSO) для распределенных сайтов. Заявки JWT обычно используются для передачи аутентифицированного пользователя Идентификационная информация между поставщиками удостоверений и поставщиками услуг для получения ресурсов от серверов ресурсов, а также может быть добавлена ​​дополнительная информация. Для другой информации объявления, необходимой для бизнес-логики, токен также может использоваться непосредственно для аутентификации или зашифровываться. Подробнее см. в этой статье.Понимание и практика аутентификации JWT (JSON Web Token)

Особенности JWT

преимущество

  • Небольшой размер для быстрой передачи
  • Существуют различные методы передачи, которые могут передаваться через параметры URL/POST/заголовки HTTP и т. д.
  • Строго структурировано. Он сам (в полезной нагрузке) содержит все сообщения проверки, связанные с пользователем, такие как доступные пользователю маршруты, срок действия доступа и т. д., серверу не нужно подключаться к базе данных для проверки достоверности информации, а полезная нагрузка поддерживает настройку для изменения вашего приложения.
  • Поддерживает междоменную аутентификацию и может применяться для единого входа.

существующие проблемы

Сам JWT (в полезной нагрузке) содержит все сообщения аутентификации, связанные с пользователем, поэтому обычно не нужно сохранять. Есть несколько проблем с этим дизайном:

  1. Токен нельзя отозвать — JWT до того, как клиент сбросит пароль, все еще можно использовать (срок действия JWT не истек или истек
  2. Токен обновления не поддерживается, и полный процесс авторизации входа необходимо выполнить после истечения срока действия JWT.
  3. Невозможно узнать, сколько JWT выдал пользователь.

Возможные решения первой проблемы:

  1. Сохраните JWT в базе данных (или Redis), чтобы его можно было проверить отдельно для каждого JWT.
  2. При сбросе пароля и т. д. необходимо аннулировать все предыдущие JWT, записать момент времени операции в базу данных (или Redis) и проверить, был ли сброшен JWT после создания JWT.

Конечно, это решение потребует еще одного запроса к базе данных, что снизит проверяемое преимущество самого JWT, а также повлияет на эффективность аутентификации.

Эта статья в основном знакомит с идеей решения второй проблемы (refresh token не поддерживается).

refresh token

Токен обновления — это концепция аутентификации OAuth2. Он генерируется вместе с токеном доступа OAuth2. Это означает обновление токена. Срок действия больше, чем у токена доступа, и его можно использовать для получения следующего токена доступа.

Если JWT необходимо добавить поддержку токена обновления, токен обновления должен соответствовать следующим условиям:

  1. Генерируется и возвращается клиенту вместе с JWT
  2. Имеет эффективное время, которое больше, чем JWT
  3. Его можно использовать только для обмена на следующий JWT, а не для аутентификации доступа.
  4. Нельзя повторно использовать (необязательно)

обновить процесс получения токена

Обновить процесс использования токена

пример кода

import jwt
import time

# 使用 sanic 作为restful api 框架 
def create_token(account_id, username):
    payload = {
        "iss": "gusibi.mobi",
        "iat": int(time.time()),
        "exp": int(time.time()) + 86400 * 7,
        "aud": "www.gusibi.mobi",
        "sub": account_id,
        "username": username,
        "scopes": ['open']
    }
    token = jwt.encode(payload, 'secret', algorithm='HS256')
    payload['grant_type'] = "refresh"
    refresh_token = jwt.encode(payload, 'secret', algorithm='HS256')
    return True, {
        'access_token': token,
        'account_id': account_id,
        "refresh_token": refresh_token
        }

# 验证refresh token 出否有效
def verify_refresh_token(token):
    payload = jwt.decode(token, 'secret', audience='www.gusibi.com', algorithms=['HS256'])
    # 校验token 是否有效,以及是否是refresh token,验证通过后生成新的token 以及 refresh_token
    if payload and payload.get('grant_type') == 'refresh':
        # 如果需要标记此token 已经使用,需要借助redis 或者数据库(推荐redis)
        return True, payload
    return False, None

# 验证token 是否有效
def verify_bearer_token(token):
    #  如果在生成token的时候使用了aud参数,那么校验的时候也需要添加此参数
    payload = jwt.decode(token, 'secret', audience='www.gusibi.com', algorithms=['HS256'])
    # 校验token 是否有效,以及不能是refresh token
    if payload and not payload.get('grant_type') == 'refresh':
        return True, payload
    return False, None

Ссылка на ссылку

использованная литература [1] Понимание OAuth 2.0:Вууху. Руан Ифэн.com/blog/2014/0…


Наконец, поблагодарите мою девушку за ее поддержку и терпимость, чем ❤️

Вы также можете ввести следующие ключевые слова в официальном аккаунте, чтобы получить исторические статьи:公号&小程序 | 设计模式 | 并发&协程

扫码关注