-
jwt pyjwt会导致jwt.encode()方法报错
-
pip install pyjwt
-
def generate_jwt(payload: dict, expiry: datetime, secret=None) -> str:
"""
生成jwt
:param payload: dict, 载荷
:param expiry: datetime 有效期
:param secret: 密钥
:return: jwt
"""
_payload = {"exp": expiry}
_payload.update(payload)
if not secret:
secret = current_app.config['JWT_SECRET']
token = jwt.encode(_payload, secret, algorithm='HS256')
return token
生成jwt,三个部分组成:载荷、密钥、加密方法
载荷中可以包含用户的信息以及exp有效期
-
def verify_jwt(token: str, secret=None) -> dict:
"""
检验token
:param token: jwt
:param secret: 密钥
:return: payload
"""
if not secret:
secret = current_app.config["JWT_SECRET"]
try:
payload = jwt.decode(token, secret, algorithms=['HS256'])
except jwt.PyJWTError as e:
current_app.logger.error(e)
payload = None
return payload
检验jwt,就是decode之前生成的jwt,然后验证其中的载荷部分的用户信息
-
def generate_token(user_id: int, refresh=True) -> tuple:
"""
生成token和refresh_token
:param user_id: 用户id
:param refresh:
:return:
"""
secret = current_app.config["JWT_SECRET"]
expiry = datetime.utcnow() + timedelta(hours=current_app.config["JWT_EXPIRY_HOURS"])
token = generate_jwt({"user_id": user_id}, expiry, secret)
if refresh:
expiry = datetime.utcnow() + timedelta(days=current_app.config["JWT_REFRESH_DAYS"])
refresh_token = generate_jwt({"user_id": user_id, "is_refresh": True}, expiry, secret)
else:
refresh_token = None
return token, refresh_token
生成token的函数,token和refresh_token就是调用generate_jwt而生成的
-
def jwt_authentication():
"""
获取请求头中的token
:return:
"""
g.user_id = None
g.is_refresh = False
token = request.headers.get("Authorization")
current_app.logger.info(f"token is {token}")
if token is not None and token.startswith("Bearer "):
token = token[7:]
payload = verify_jwt(token)
current_app.logger.info(f"payload is {payload}")
if payload is not None:
g.user_id = payload.get("user_id")
g.is_refresh = payload.get("is_refresh", False)
app.before_request(jwt_authentication)
给flask添加钩子函数,当请求中包含token时,设定g中的user_id 和 is_refresh
-
def login_required(func):
@wraps(func)
def wrapper(*args, **kwargs):
if g.user_id is not None and g.is_refresh is False:
return func(*args, **kwargs)
else:
current_app.logger.warn("Invalid token")
return {
"msg": "Invalid token"
}, 401
return wrapper
使用装饰器,如果g中已有user_id说明用户已登录