前言
之千我们已经实现了哈希密码,接下来我们实现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"
}
}
后续
如何在其他接口中使用该令牌进行验证呢,后面再进行分享。