1. Découvrez Token pour la première fois
Permettez-moi de parler de ce qu'est un token. Le token ici fait référence à JWT (Json Web Token) par défaut.
Découvrez Json Web Token
type de jeton
Jeton traditionnel
Le jeton traditionnel est qu'après la connexion d'un utilisateur, le serveur renvoie un jeton à l'utilisateur pour qu'il l'enregistre. Ce jeton peut être une combinaison de plusieurs lettres aléatoires et le serveur conserve le même jeton (par exemple, en utilisant redis pour stocker le jeton)
Lorsque l'utilisateur accède à d'autres interfaces, il doit porter ce jeton, puis le serveur juge si le jeton existe dans redis pour juger si l'utilisateur s'est connecté ou a les autorisations correspondantes
JWT (jeton Web json)
Contrairement aux jetons traditionnels, les jetons Web json n'ont pas besoin d'être conservés sur le serveur.
Flux de traitement:
Une fois que l'utilisateur s'est connecté, le serveur calcule et renvoie un jeton chiffré selon certaines règles. Le jeton contient certaines informations nécessaires sur l'utilisateur, telles que l'identifiant de l'utilisateur et l'heure d'expiration du jeton.
Lorsque les utilisateurs accèdent à d'autres interfaces, ils doivent transporter ce jeton, puis le serveur vérifie ce jeton avec un mot de passe
- Vérifiez que le jeton est le jeton envoyé par le serveur
- Vérifier l'heure d'expiration du jeton
Une fois que tout est correct, l'utilisateur est considéré comme connecté et dispose des autorisations correspondantes
Où le jeton sera-t-il utilisé?
Dans notre développement avec séparation des frontaux et des back-ends, il est souvent nécessaire de fournir une authentification pour les services multi-end, tels que le mobile, le web et les petits programmes. Il y a des milliers d'utilisateurs et des milliers d'interfaces.
Et comment pouvons-nous nous assurer que chaque interface autorise uniquement les utilisateurs autorisés à y accéder? (Par exemple, seul l'administrateur peut accéder ou seul l'utilisateur connecté peut accéder)
La solution consiste à renvoyer un JWT à l'utilisateur, puis à juger à partir de ce jeton si l'utilisateur actuel de l'interface d'accès répond à nos paramètres
2. Caractéristiques de Json Web Token
avantage
- Pas besoin de stocker les informations de statut de connexion de l'utilisateur sur le serveur (comme redis)
- Le même jeton peut être utilisé dans différents serveurs, environnements et même différents services d'entreprise (tant que la clé est configurée)
- Peut être utilisé sur mobile, Web, applet, etc.
Désavantage
Bien sûr, il y a des inconvénients
Par exemple, la génération et l'analyse du jeton prennent du temps. Par rapport aux méthodes traditionnelles de vérification des jetons, la génération et l'analyse JWT prendront plus de temps.
Par exemple, vous ne pouvez pas annuler un token existant (si le token est divulgué, même si l'utilisateur a changé le mot de passe pendant la période de validité du token, l'attaquant peut toujours utiliser le token comme il le souhaite)
3. Principe du jeton
Si vous êtes entré sur le site Web de génération de JWT en ligne , vous pouvez voir cette image
Le jeton Web Json contient trois parties, l'en-tête, les données et la signature
tête
L'en-tête peut mettre des informations sur le jeton, telles que des informations sur l'algorithme de cryptage, l'heure à laquelle le jeton a été créé et l'heure d'expiration, puis utiliser base64 pour le cryptage
Remarque (les données chiffrées en base64 peuvent être déchiffrées par n'importe qui, ce qui équivaut à la transparence)
tel que
{
"typ": "jwt", # token类型
"iat": 1603426198, # 生成时间
"exp": 1603426298 # 过期时间
}
Les données
Les données peuvent mettre un identifiant d'utilisateur, un niveau d'autorisation, etc., mais veuillez ne pas mettre de données secrètes, telles que (mot de passe de l'utilisateur, nom réel de l'utilisateur)
Remarque (car tout le monde peut déchiffrer l'en-tête et les données en utilisant base64)
{
"say": "我爱你",
"from": "音宫",
"to": "小姐姐",
"uid": 1,
"role": "admin"
}
Signature
La partie signature est l'essence même du JWT. Les deux chaînes d'en-tête et de données sont hachées et chiffrées. Ce hachage est différent du chiffrement base64. Le chiffrement par hachage nécessite un mot de passe, qui ne peut pas être divulgué à l'utilisateur. , Autrement dit, le contenu chiffré est irréversible
Par exemple, la méthode de cryptage est la suivante
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
Qu'est-ce que ça veut dire?
Par exemple, la partie en-tête enregistre la création à 7 heures et l'expiration à 8 heures, ce qui signifie que la période de validité est d'une heure.
La partie de données enregistre l'ID d'un certain utilisateur.
À ce stade, une fois le serveur crypté avec un mot de passe, une chaîne de chaînes sera formée (tant que les données dans l'en-tête et les parties de données ne sont pas modifiées, la même chaîne sera formée à chaque fois que le cryptage est effectué)
Vous pouvez accéder à l'interface de service entre 7 et 8 heures et peut être utilisé normalement
Cependant , à 9 heures, le pirate a trouvé votre jeton, mais le jeton a expiré, puis le pirate a modifié l'heure d'expiration de l'en-tête, puis a utilisé ce jeton pour accéder à l'interface de service
À ce moment, il y aura une erreur, pourquoi?
Parce qu'après la modification des informations d'en-tête, la signature changera, mais le pirate n'a pas généré le mot de passe du jeton et le pirate ne peut pas construire la signature correcte.
Lorsque le jeton est vérifié en arrière-plan, l'en-tête et la partie données seront cryptés avec un mot de passe pour générer une signature, puis comparés avec le jeton soumis pour voir s'il est cohérent
4. Générer un jeton
Python est utilisé ici pour démontrer la génération de jeton
Nous devons d'abord importer plusieurs packages
import time
import json
import base64
import hashlib
import hmac
Ce sont des outils permettant d'obtenir l'heure actuelle, de générer et d'analyser le format json et de chiffrer
Préparez deux paramètres à l'avance
exp=60 # token有效期 秒
salt="xxx" # 加密的密码 不能让用户知道
En-tête de traitement
headers = {
"typ": "ygt",
"exp": int(time.time() + exp) # 过期时间戳
}
En-tête chiffré
first = base64.urlsafe_b64encode(json.dumps(headers, separators=(',', ':')).encode('utf-8').replace(b'=', b'')).decode(
'utf-8').replace('=', '')
Traitement de la charge utile des données
La charge utile stocke ici certaines données utilisateur (uid, rôle, etc.) Remarque: ne mettez pas de données privées ici (comme les mots de passe utilisateur, etc.)
payload = {
"uid": 1,
"author": "好音宫",
"admin": 1
}
Charge utile chiffrée
second = base64.urlsafe_b64encode(json.dumps(payload, separators=(',', ':')).encode('utf-8').replace(b'=', b'')).decode(
'utf-8').replace('=', '')
Signature cryptographique
La troisième partie est la signature, la signature doit utiliser du sel, qui est le mot de passe crypté
Après avoir épissé les deux premières parties, utilisez le cryptage par hachage pour crypter les deux parties de la signature pour obtenir une chaîne, appelée signature
# 拼接前两部分
first_second = f"{first}.{second}"
# 对前面两部分签名呀
third = base64.urlsafe_b64encode(
hmac.new(salt.encode('utf-8'), first_second.encode('utf-8'), hashlib.sha256).digest()).decode('utf-8').replace('=',
'')
# 拼接签名和前两部分,就叫做token啦
token = ".".join([first, second, third])
print(token)
Accédez au site officiel pour analyser les informations du jeton
Imprimez notre token, copiez le token
eyJ0eXAiOiJ5Z3QiLCJleHAiOjE2MDM0Mjk4MDd9.eyJ1aWQiOjEsImF1dGhvciI6Ilx1NTk3ZFx1OTdmM1x1NWJhYiIsImFkbWluIjoxfQ.XT6h40ghE6aLxCisrLMbJG8stcP_ujMt1IpxVOMrO0w
On constate que les données sont les mêmes que notre définition, ce qui prouve que les deux premières parties sont normales, et l'étape suivante consiste à vérifier le jeton
Analyser le jeton pour extraire les données
Essayez d'analyser le jeton et d'extraire les données
Code JWT de référence
# 提取出header、payload、sign
headers = token.split(".")[0]
payload = token.split(".")[1]
sign = token.split(".")[2]
Pour déterminer si le jeton est valide, utilisez la même méthode pour chiffrer l'en-tête et la charge utile, et voyez si la signature obtenue est la même que le signe attaché au jeton
headers_payload = f"{headers}.{payload}"
new_sign = base64.urlsafe_b64encode(
hmac.new(salt.encode('utf-8'), headers_payload.encode('utf-8'), hashlib.sha256).digest()).decode(
'utf-8').replace(
'=',
'')
print(new_sign == sign)
# if new_sign == sign: 判断是否相等
S'ils sont identiques, prouvez que le jeton est valide, puis obtenez les informations d'en-tête ou de charge utile
if isinstance(payload, str):
payload = payload.encode('ascii')
rem = len(payload) % 4
if rem > 0:
payload += b'=' * (4 - rem)
# 上面这一部分是解密的部分数据补全格式
payload_data = base64.urlsafe_b64decode(payload) # 解码
data = json.loads(payload_data) # 加载payload信息为可以通过get方法获取里面的值
print(data.get("uid")) # 打印token里面的payload部分中的uid数据信息
print(data.get("author")) # 打印token里面的payload部分中的uid数据信息
Jusqu'à ce point
Nous avons créé le jeton avec succès et pouvons extraire la valeur du jeton
La prochaine étape consiste à encapsuler dans une classe en fonction de nos propres besoins
5. Articles de référence
documentation du site officiel de jwt.io
Python JWT 使用, par dawsonenjoy
Introduction à JSON Web Token , par Ruan Yifeng
Bienvenue à aimer ma page d'accueil personnelle GitHub
Hi Caiji