如何在请求上下文之外伪造JWT授权并获取当前身份



我正在创建一个带有JWT授权的Flask应用程序,并尝试使用PyTest测试服务。

我成功地向端点添加了测试,但当我尝试为某个函数添加单元测试时,我无法访问当前用户,因为flask_jwt_extended.get_current_user()返回None。

这里有一个简单的例子:

@api.route('/listings', methods=['POST'])
@jwt_required
def create_listing():
payload = request.json
listing = listing_svc.create(payload)
return listing

def create(payload):
listing = ListingSchema().load(payload, db.session).data

class ListingSchema(ModelSchema):
id = field_for(Project, 'id', dump_only=True)
creator_user_id = field_for(Project, 'creator_user_id')
# ...
@pre_load
def set_creator_id(self, data):
current_user = flask_jwt_extended.get_current_user()
data['creator_user_id'] = current_user.id

当我使用app_context:授权并发送请求时,它就起作用了

with client.application.app_context():
rv = client.post('/listings',
# ...
)

但我需要的是在不向客户端发送请求的情况下测试create功能。在这种情况下,flask_jwt_extended.get_current_user()返回None,所以我认为在运行此函数之前,我应该以某种方式设置请求上下文。

我试着这么做。。。

fake_payload = {}
with client.application.test_request_context('/listings', headers={'Authorization': 'Bearer ' + access_token}):
create(fake_payload)

但仍然得到current_userNone

这就是我获得代币的方式:

def login(email, password):
user = get_by_email(email)
if user and check_password_hash(user.password, password):
return access_token = flask_jwt_extended.create_access_token(identity=email)

如果您正在编写单元测试,使用mock可能会有所帮助。对于扩展了flask jwt的jwt授权,您可以修补从jwt_required decorator调用的verify_jwt_in_request方法。然后,您还可以修补get_jwt_identity函数以返回测试用户名。例如:

from unittest.mock import patch

@patch('path.to.some.code.get_jwt_identity')
@patch('flask_jwt_extended.view_decorators.verify_jwt_in_request')
def test_some_code(mock_jwt_required, mock_jwt_identity):
mock_jwt_identity.return_value = 'user1'
# Test jwt protected endpoint

注:此补丁适用于最新版本的flask jwt extended==3.21.0。代码可能会随着新版本而更改。

这个问题来自很久以前,但这里是供更多读者使用的解决方案。

您需要激活app_context,然后激活request_context,最后调用decorator正在调用的函数,即verify_jwt_in_request:


fake_payload = {}
with client.application.app_context():
with client.application.test_request_context('/listings', headers={'Authorization': 'Bearer ' + access_token}):
verify_jwt_in_request()
create(fake_payload)

现在你有了当前用户设置的

如果你真的想进行单元测试,你需要一次对一个函数进行单元测试。在我看来,这是真正的测试驱动开发。因此,首先编写create的测试,然后加载等等。使用补丁来模拟对其他函数的调用的功能。

相关内容

  • 没有找到相关文章

最新更新