1. Conozca Token por primera vez
Permítanme hablar sobre lo que es un token. El token aquí se refiere a JWT (Json Web Token) por defecto.
Experimente Json Web Token
tipo de token
Token tradicional
El token tradicional es que después de que un usuario inicia sesión, el servidor le devuelve un token al usuario para que lo guarde. Este token puede ser una combinación de varias letras aleatorias y el servidor retiene el mismo token (por ejemplo, usando redis para almacenar el token)
Cuando el usuario accede a otras interfaces, debe llevar este token, y luego el servidor juzga si este token existe en redis para juzgar si el usuario ha iniciado sesión o tiene los permisos correspondientes.
JWT (token web json)
A diferencia de los tokens tradicionales, los tokens web json no necesitan mantenerse en el servidor.
Flujo de procesamiento:
Una vez que el usuario inicia sesión, el servidor calcula y devuelve un token cifrado de acuerdo con ciertas reglas. El token contiene cierta información necesaria del usuario, como la identificación del usuario y la fecha de vencimiento del token.
Cuando los usuarios acceden a otras interfaces, deben llevar este token, y luego el servidor verifica este token con una contraseña
- Verifique que el token sea el token enviado por el servidor
- Verificar el tiempo de vencimiento del token
Una vez que todo está correcto, se considera que el usuario ha iniciado sesión y tiene los permisos correspondientes.
¿Dónde se usará el token?
En nuestro desarrollo, donde el front-end y el back-end están separados, a menudo es necesario proporcionar autenticación para servicios multi-end, como móviles, web y pequeños programas Hay miles de usuarios y miles de interfaces.
¿Y cómo podemos asegurarnos de que cada interfaz solo permita el acceso de usuarios autorizados? (Por ejemplo, solo el administrador puede acceder o solo el usuario que inició sesión puede acceder)
La solución es devolver un JWT al usuario y luego juzgar a partir de este token si el usuario de la interfaz de acceso actual cumple con nuestra configuración.
2. Características de Json Web Token
ventaja
- No es necesario almacenar la información del estado de inicio de sesión del usuario en el servidor (como redis)
- El mismo Token se puede usar en diferentes servidores, entornos e incluso diferentes servicios comerciales (siempre que la clave esté configurada)
- Se puede usar en dispositivos móviles, web, applet, etc.
Desventaja
Por supuesto que hay desventajas
Por ejemplo, se necesita tiempo para generar y analizar el token. En comparación con los métodos tradicionales de verificación de token, la generación y el análisis de JWT llevará más tiempo.
Por ejemplo, el token existente no se puede cancelar (si el token se filtra, incluso si el usuario ha cambiado la contraseña dentro del período de validez del token, el atacante aún puede usar el token para hacer lo que quiera)
3. Principio de token
Si ha ingresado al sitio web de generación de JWT en línea , puede ver esta imagen
El token web Json contiene tres partes, encabezado, datos y firma
cabeza
El encabezado puede incluir información sobre el token, como información sobre el algoritmo de cifrado, la hora en que se creó el token y el tiempo de vencimiento, y luego usar base64 para el cifrado.
Nota (los datos cifrados en base64 pueden ser descifrados por cualquier persona, lo que equivale a transparentes)
como
{
"typ": "jwt", # token类型
"iat": 1603426198, # 生成时间
"exp": 1603426298 # 过期时间
}
datos
Los datos pueden incluir alguna identificación de usuario, nivel de permiso, etc., pero no coloque datos secretos, como (contraseña del usuario, nombre real del usuario)
Nota (porque cualquiera puede descifrar el encabezado y los datos usando base64)
{
"say": "我爱你",
"from": "音宫",
"to": "小姐姐",
"uid": 1,
"role": "admin"
}
firma
La parte de la firma es la esencia de JWT. Las dos cadenas de encabezado y datos están cifradas y cifradas. Este hash es diferente del cifrado base64. El cifrado hash requiere una contraseña, que no se puede revelar al usuario. , Es decir, el contenido cifrado es irreversible
Por ejemplo, el método de cifrado es el siguiente
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
Qué significa eso?
Por ejemplo, la parte del encabezado registra la creación a las 7 en punto y la expiración a las 8 en punto, lo que significa que el período de validez es de una hora.
La parte de datos registra la identificación de un determinado usuario.
En este momento, después de cifrar el servidor con una contraseña, se formará una cadena de cadenas (siempre que los datos en el encabezado y las partes de datos no se modifiquen, se formará la misma cadena cada vez que se realice el cifrado)
Puede acceder a la interfaz de servicio entre las 7 y las 8 en punto y se puede utilizar normalmente
Sin embargo , a las 9 en punto, el pirata informático encontró su token, pero el token expiró, luego el pirata informático cambió la hora de vencimiento del encabezado y luego usó este token para acceder a la interfaz del servicio
En este momento habrá un error, ¿por qué?
Porque después de que se cambia la información del encabezado, la firma cambiará, pero el hacker no generó la contraseña del token y el hacker no puede construir la firma correcta.
Cuando el token se verifica en segundo plano, el encabezado y la parte de datos se cifrarán con una contraseña para generar una firma y luego se compararán con el token enviado para ver si es coherente
4. Generar token
Python se usa aquí para demostrar la generación de token
Primero tenemos que importar varios paquetes
import time
import json
import base64
import hashlib
import hmac
Son herramientas para obtener la hora actual, generar y analizar el formato json y cifrar
Prepare dos parámetros de antemano
exp=60 # token有效期 秒
salt="xxx" # 加密的密码 不能让用户知道
Encabezado de procesamiento
headers = {
"typ": "ygt",
"exp": int(time.time() + exp) # 过期时间戳
}
Encabezado cifrado
first = base64.urlsafe_b64encode(json.dumps(headers, separators=(',', ':')).encode('utf-8').replace(b'=', b'')).decode(
'utf-8').replace('=', '')
Procesamiento de carga útil de datos
La carga útil aquí almacena algunos datos del usuario (uid, rol, etc.). Nota: No coloque aquí datos privados (como contraseñas de usuario, etc.)
payload = {
"uid": 1,
"author": "好音宫",
"admin": 1
}
Carga útil cifrada
second = base64.urlsafe_b64encode(json.dumps(payload, separators=(',', ':')).encode('utf-8').replace(b'=', b'')).decode(
'utf-8').replace('=', '')
Firma criptográfica
La tercera parte es la firma, la firma necesita usar salt, que es la contraseña encriptada
Después de empalmar las dos primeras partes, use el cifrado hash para cifrar las dos partes de la firma para obtener una cadena, que se llama firma.
# 拼接前两部分
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)
Vaya al sitio web oficial para analizar la información del token
Imprime nuestro token, copia el token
eyJ0eXAiOiJ5Z3QiLCJleHAiOjE2MDM0Mjk4MDd9.eyJ1aWQiOjEsImF1dGhvciI6Ilx1NTk3ZFx1OTdmM1x1NWJhYiIsImFkbWluIjoxfQ.XT6h40ghE6aLxCisrLMbJG8stcP_ujMt1IpxVOMrO0w
Se encuentra que los datos son los mismos que en nuestra definición, lo que prueba que las dos primeras partes son normales, y el siguiente paso es verificar el token.
Analizar el token para extraer datos
Intente analizar el token y extraer datos
Código JWT de referencia
# 提取出header、payload、sign
headers = token.split(".")[0]
payload = token.split(".")[1]
sign = token.split(".")[2]
Para determinar si el token es válido, use el mismo método para cifrar el encabezado y la carga útil, y vea si la firma obtenida es la misma que el signo adjunto al token
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: 判断是否相等
Si son iguales, pruebe que el token es válido y luego obtenga el encabezado o la información de carga útil
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数据信息
A este punto
Hemos creado correctamente el token y podemos extraer el valor del token.
El siguiente paso es encapsularlo en una clase de acuerdo con nuestras propias necesidades.
5. Artículos de referencia
Documentación del sitio web oficial jwt.io
Python JWT 使用, por dawsonenjoy
Tutorial introductorio de JSON Web Token , por Ruan Yifeng
Bienvenido a me gusta en mi página de inicio personal de GitHub
Hi Caiji