You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask中JWT解码装饰器引发端点函数覆盖断言错误

问题

编写Flask端点时添加JWT解码装饰器后,持续抛出错误:

AssertionError: View function mapping is overwriting an existing endpoint function

尝试通过装饰器解码JWT令牌,将payload传递给被装饰函数并返回响应,代码片段如下:

def get_config(section):
    with open('./config/configurations.yml',"r") as file:
        config = yaml.safe_load(file)
    return config[section]

def decode_jwt_token(token, secret_key, algo):
    try:
        decoded_payload = jwt.decode(token,secret_key,algorithms=[algo])
        return decoded_payload
    except jwt.ExpiredSignatureError:
        print("Token has expired")
    except jwt.InvalidTokenError:
        print("Invalid Token")

def decodeJWT(func):
    def wrapper(**kwargs):
        config = get_config("jwt")
        auth_header = request.headers.get("Authorization")
        if auth_header and auth_header.startswith('Bearer'):
            token = auth_header.split(' ')[1]
            payload = decode_jwt_token(token, config["secret"], config["jwt_algorithm"])
            return func(payload=payload)
        else:
            return jsonify({'message': 'Invalid Token'}), 401
    return wrapper

@app.route("/test",methods=["GET"])
@decodeJWT
def test(**kwargs):
    payload = kwargs.get("payload",None)
    if payload is None:
        return jsonify({'message': 'Token is invalid'}), 401
    return jsonify({'message': 'This is a secure message', 'data': payload}), 200

完整报错信息:

Traceback (most recent call last):
  File "C:\Users\al90935\Documents\flask_rest_api\app.py", line 45, in <module>
    def test(**kwargs):
  File "C:\Users\al90935\Documents\flask_env\lib\site-packages\flask\sansio\scaffold.py", line 362, in decorator
    self.add_url_rule(rule, endpoint, f, **options)
  File "C:\Users\al90935\Documents\flask_env\lib\site-packages\flask\sansio\scaffold.py", line 47, in wrapper_func
    return f(self, *args, **kwargs)
  File "C:\Users\al90935\Documents\flask_env\lib\site-packages\flask\sansio\app.py", line 657, in add_url_rule
    raise AssertionError(
AssertionError: View function mapping is overwriting an existing endpoint function: wrapper

请问哪里出错了?是否与传递payload参数有关?

原因与解决方法

这个错误和传递payload参数无关,核心问题是Flask默认用视图函数的名称作为endpoint标识,而你的装饰器返回的wrapper函数没有保留原视图函数的元数据(包括函数名),导致Flask将所有被该装饰器修饰的视图都识别为同名的wrapper端点,从而触发覆盖冲突。

解决方法是给装饰器的wrapper函数添加functools.wraps装饰器,它会把原视图函数的名称、文档字符串等元数据复制到wrapper上,让Flask能正确识别每个视图的唯一endpoint。

修改后的装饰器代码如下:

import functools  # 需先导入functools模块

def decodeJWT(func):
    @functools.wraps(func)  # 添加这一行,保留原函数元数据
    def wrapper(**kwargs):
        config = get_config("jwt")
        auth_header = request.headers.get("Authorization")
        if auth_header and auth_header.startswith('Bearer'):
            token = auth_header.split(' ')[1]
            payload = decode_jwt_token(token, config["secret"], config["jwt_algorithm"])
            return func(payload=payload)
        else:
            return jsonify({'message': 'Invalid Token'}), 401
    return wrapper

额外补充两个优化建议:

  • decode_jwt_token函数在捕获异常后没有返回值,会导致payload为None,建议在异常分支明确返回None,或者直接抛出Flask的HTTP异常(如abort(401)),让错误处理更清晰。
  • 可以缓存get_config的结果,避免每次请求都读取yaml文件,提升接口性能。

内容的提问来源于stack exchange,提问作者aiman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 22:55:04