Creación y verificación de python-fastapi-token

Inicio de sesión de autenticación de token JWT

El blog anterior hablaba sobre la obtención y verificación de parámetros de solicitud. En la práctica, este artículo demuestra una autenticación JWT básica. Nuestra empresa utiliza dos métodos de token para la verificación, un token de solicitud, un token de actualización y el tiempo de vencimiento del token. Breve, dedicado a los datos de la solicitud , el token de actualización está dedicado a actualizar el token de solicitud caducado.

sitio web oficial de jwt https://jwt.io/

Si aún no comprende JWT, debe analizar detenidamente el conocimiento de JWT. La autenticación JWT es actualmente un método de autenticación muy popular en la separación de front-end y back-end: se compone de tres secciones. La primera sección suele ser un algoritmo de cifrado, y la segunda sección es La información personalizada que almacena (cualquier persona que no esté cifrada puede ir a https://jwt.io/ para ver los datos) El tercer párrafo son los parámetros de firma generados en los párrafos primero y segundo para asegurarse de que el token no ha sido modificado

Generar token

Biblioteca dependiente

Python actualmente tiene varias bibliotecas para implementar la verificación jwt

  • python-jose
  • pyjwt
  • jwcrypto
  • authlib

Aquí no hay demostración de comparación, solo elija una

Cáscara

pip install python-jose

Demostración simple

 

from datetime import datetime, timedelta

from jose import jwt

# 加密密钥 这个很重要千万不能泄露了
SECRET_KEY = "kkkkk"

# 设置过期时间 现在时间 + 有效时间    示例5分钟
expire = datetime.utcnow() + timedelta(minutes=5)

# exp 是固定写法必须得传  sub和uid是自己存的值
to_encode = {"exp": expire, "sub": str(123), "uid": "12345"}

# 生成token 
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm="HS256")
print(encoded_jwt) 
# eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTU1MDg5MzQsInN1YiI6IjEyMyIsInVpZCI6IjEyMzQ1In0.lttAYe808lVQgGhL9NXei2bbC1LIGs-SS0l6qfU_QxU

Puedes copiarlo a https://jwt.io/ para resolverlo y ver

Inserte la descripción de la imagen aquí

Inserte la descripción de la imagen aquí

 

Descifrar token

payload = jwt.decode(
            "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTU1MDg5MzQsInN1YiI6IjEyMyIsInVpZCI6IjEyMzQ1In0.lttAYe808lVQgGhL9NXei2bbC1LIGs-SS0l6qfU_QxU",
            SECRET_KEY, algorithms="HS256"
        )
print(payload)
# {'exp': 1595508934, 'sub': '123', 'uid': '12345'}

La forma correcta de descifrar

El método anterior es cuando el token es correcto y no ha caducado, se resolverá normalmente. Ahora agregue la captura de excepciones comunes.

from jose.exceptions import ExpiredSignatureError, JWTError
try:
    payload = jwt.decode(
                "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTU1MDk0ODQsInN1YiI6IjEyMyIsInVpZCI6IjEyMzQ1In0.deulPSOPfON-lfbXtvQfTfc-DwqvFoQqv7Y1BhMecBw",
                SECRET_KEY, algorithms="HS256"
            )
    print(payload)
# 当然两个异常捕获也可以写在一起,不区分
except ExpiredSignatureError as e:
    print("token过期")
except JWTError as e:
    print("token验证失败")

Realice el inicio de sesión de autenticación JWT en FastAPI

El proceso de cifrado y descifrado jwt mencionado anteriormente es claro. Este paso es muy simple. Primero, cree un security.pyarchivo dedicado al cifrado y descifrado.

from datetime import datetime, timedelta
from typing import Any, Union, Optional
from jose import jwt
from fastapi import Header
# 导入配置文件
from setting import config

ALGORITHM = "HS256"


def create_access_token(
    subject: Union[str, Any], expires_delta: timedelta = None
) -> str:
    """
    # 生成token
    :param subject: 保存到token的值
    :param expires_delta: 过期时间
    :return:
    """
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(
            minutes=config.ACCESS_TOKEN_EXPIRE_MINUTES
        )
    to_encode = {"exp": expire, "sub": str(subject)}
    encoded_jwt = jwt.encode(to_encode, config.SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


def check_jwt_token(
     token: Optional[str] = Header(None)
) -> Union[str, Any]:
    """
    解析验证 headers中为token的值 担任也可以用 Header(None, alias="Authentication") 或者 alias="X-token"
    :param token:
    :return:
    """

    try:
        payload = jwt.decode(
            token,
            config.SECRET_KEY, algorithms=[ALGORITHM]
        )
        return payload
    except (jwt.JWTError, jwt.ExpiredSignatureError, AttributeError):
        # 抛出自定义异常, 然后捕获统一响应
        raise custom_exc.TokenAuthError(err_desc="access token fail")

Se debe definir lo anterior, la forma de cifrar y descifrar el token, este paso es iniciar sesión para generar el token

# 从刚刚定义好jwt的文件导入生成方法
from security import create_access_token
from pydantic import BaseModel


class UserInfo(BaseModel):
    username: str
    password: str


@router.post("/login/access-token", summary="用户登录认证")
async def login_access_token(
        *,
        db: Session = Depends(deps.get_db),
        user_info: UserInfo,
) -> Any:
    """
    用户登录
    :param db:
    :param user_info:
    :return:
    """

    # 验证用户账号密码是否正确
     user = curd_user.authenticate(db, email=user_info.username, password=user_info.password)
    if not user:
        logger.info(f"用户邮箱认证错误: email{user_info.username} password:{user_info.password}")
        return response_code.resp_500(message="用户名或者密码错误")
    elif not curd_user.is_active(user):
        return response_code.resp_500(message="用户邮箱未激活")

    # 如果用户正确通过 则生成token
    # 设置过期时间
    access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)

    # 登录token 只存放了user.id
    return response_code.resp_200(data={
        "token": create_access_token(user.id, expires_delta=access_token_expires),
    })

Token de verificación

Este paso se utiliza from fastapi import Dependspara validar los encabezados tokenen la security.pydefinición del parámetro de token anterior que ha tomado los encabezados del archivo

from typing import Any, Union

from fastapi import Depends
# 从刚刚定义好jwt的文件导入解密方法
from security import check_jwt_token

@router.get("/user/info", summary="获取用户信息", response_model=user.UserInfo)
async def get_user_info(
    token_data: Union[str, Any] = Depends(check_jwt_token)  
) -> Any:
    """
    获取用户信息
    :param token_data:
    :return:
    """
    print(token_data)
    # 这个状态能响应说明token验证通过
    return response_code.resp_200(data={
        "username": "用户信息"
    })

Entonces, el método de solicitud correcto debería ser así. Lleve el campo del token en los encabezados. Si lo repite de nuevo, también puede usar un check_jwt_tokenalias del token en el método. El más común es Authentication¿por qué no escribirlo directamente en el parámetro check_jwt_token Authentication? Porque los parámetros están escritos en mayúsculas y no comienzan con ellos, cumple con la especificación pep8 de programación de Python, es decir X-Token, la variable no admite -símbolos, por lo que se escribe como un alias.

import requests

res = requests.get("http://127.0.0.1:8000/user/info", headers={
    "token": "xxxx",
    "content-type": "application/json"
})

para resumir

Familiarizado con el método de descifrado y generación de tokens jwt en la primera mitad, puede aplicarlo en cualquier marco de Python (Django, Flask, Tornado, Sanic, Bottle, etc.). Muchas extensiones encapsuladas son esencialmente las mismas. Me gusta usar extensiones.

La autenticación Jwt es realmente muy simple. Para comprender el proceso de cifrado y descifrado, es suficiente comprender un poco el principio. Con redis más adelante, puede completar operaciones como el inicio de sesión único. También existe el problema de la renovación del token. Por ejemplo, está escribiendo un blog y el token no es válido antes de que finalice el blog. Cuando se envía el resultado, la autenticación del token falla y se requiere la renovación de la detección de latidos del token.

Dirección de GitHub del código completo

Mi propio generador de proyectos FastAPI https://github.com/CoderCharm/fastapi-mysql-generator

GitHub https://github.com/CoderCharm/FastAdmin/blob/master/backend/app/api/api_v1/auth/views.py#L32


Autor: Wang Right

Enlace del artículo: https://www.charmcode.cn/article/2020-07-23_fastapi_jwt

Declaración de derechos de autor: ¿ Keke desea utilizar los artículos de forma gratuita? Los derechos de autor de este artículo pertenecen al autor, indique la fuente en cualquier forma de reimpresión. https://www.charmcode.cn !

FastAPI


Fuente: charmcode.cn
Autor: Wang
Enlace del artículo derecho : https://www.charmcode.cn/article/2020-07-23_fastapi_jwt ¿
Keke quiere un artículo de prostituta blanca? Los derechos de autor de este artículo pertenecen al autor, indique la fuente en cualquier forma de reimpresión.

Supongo que te gusta

Origin blog.csdn.net/weixin_42100456/article/details/109139023
Recomendado
Clasificación