Python自定义authenticated装饰器valid为True仍走else分支问题
问题根因
装饰器的校验逻辑存在两个核心错误,导致永远无法命中合法分支:
- 参数收集逻辑错误:调用
message_friends(user1)时,user1是作为位置参数传入的,会被wrapper的*args收集为元组的第一个元素,**kwargs始终为空字典,原代码判断'valid' in kwargs永远不成立。 - 校验目标错误:原逻辑是检查函数调用时有没有传入名为
valid、值为True的关键字参数(即必须写成message_friends(user1, valid=True)才会触发if分支),根本没有读取传入的user字典内部的valid字段,和需求要求的“校验user对象的valid属性”完全偏离;且这种逻辑下哪怕传入无效用户,只要额外带valid=True的关键字参数就会被放行,完全起不到认证作用。
修复后代码
user1 = { 'name': 'Sorna', 'valid': True } def authenticated(fn): def wrapper(*args, **kwargs): # 兼容位置传参、关键字传参两种方式获取user对象 user = kwargs.get('user') if not user and args: user = args[0] # 校验user对象内部的valid字段 if user and user.get('valid') is True: return fn(*args, **kwargs) print('sorry not valid') return wrapper @authenticated def message_friends(user): print('message has been sent') # 测试合法用户 message_friends(user1) # 输出:message has been sent # 测试非法用户 user2 = {'name': 'InvalidUser', 'valid': False} message_friends(user2) # 输出:sorry not valid
关键注意点
- 位置参数会被
*args按传入顺序收集为元组,关键字参数才会被**kwargs收集为字典,做参数校验时需要同时覆盖两种传参场景。 - 做用户认证校验时,要直接操作传入的用户实体对象,不要在函数参数字典里查找和业务字段同名的键,避免逻辑绕过。
- 如果业务中
valid字段允许用真值(比如1、非空判定标记等)代表合法,可以把is True的严格身份判断改为普通真值判断,适配更多业务场景。
内容的提问来源于stack exchange,提问作者Panagiotis Repanas
相关产品推荐
相关产品推荐

