基于FastApi框架测试平台(7)-Bearer JWT 令牌验证

317 阅读2分钟

前言

之千我们已经实现了哈希密码,接下来我们实现Bearer JWT 令牌验证

JWT

JSON网络令牌。JWT 是一种将JSON对象编码为没有空格且难以理解的长字符串的标准。

示例

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2ODg2MjQzMDcsInN1YiI6IjIifQ.m19KgEudAhGbUTk3T5cCNeYJmTACDHyzPo-pNzDp2Ls

安装python-jose

安装 python-jose,在 Python 中生成和校验 JWT 令牌:pip install python-jose

Python-jose 需要安装配套的加密后端,官方文档中推荐的后端是:pyca/cryptography。我们这里安装cryptography:pip install cryptography

当然也可以一起安装:pip install python-jose[cryptography]

JWT令牌

JWT 令牌签名的随机密钥

执行命令:openssl rand -hex 32

输出:fbb4708158832eee84ec733cb358e71ed382e9d8e20810e44039305451e11a1a

将其写入配置文件:

SECRET_KEY: str = 'fbb4708158832eee84ec733cb358e71ed382e9d8e20810e44039305451e11a1a'

指定 JWT 令牌签名算法

同样写入配置文件

ALGORITHM: str = "HS256"

令牌过期时间

ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 # 分钟

生成令牌

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=settings.ACCESS_TOKEN_EXPIRE_MINUTES
        )
    to_encode = {"exp": expire, "sub": str(subject)}
    encoded_jwt = jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)
    return encoded_jwt

修改登录接口

我们已经可以生成令牌了,改造登录接口使返回真正的JWT 访问令牌。

@router.post("/login", response_model=user_schema.Token)
def login(user: user_schema.UserCreate):
    user, err = UserService.login(user.username, user.password)
    if err is not None:
        return resp_error(USER_ERROR_A0200, msg=err, status_code=status.HTTP_401_UNAUTHORIZED)
    access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
    data = {
        "token": UserToken.create_access_token(
            user.id, expires_delta=access_token_expires
        ),
        "token_type": "bearer"
    }
    return resp_success(data, msg="登录成功")

启动服务,请求登录接口,我们可以看到返回内容

{
  "code": 0,
  "msg": "登录成功",
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2ODg2MjYxNzksInN1YiI6IjIifQ.aOGxCERYqD2IbWz7NKHfEJfejrICXX9WrwfkYSFA9pc",
    "token_type": "bearer"
  }
}

后续

如何在其他接口中使用该令牌进行验证呢,后面再进行分享。