简体   繁体   English

如何在Flask中对HTTP摘要式身份验证进行单元测试?

[英]How do I unit test HTTP Digest Authentication in Flask?

I've got a flask app that implements a REST api. 我有一个实现REST api的flask应用程序。 For reasons, I'm using HTTP Digest Authentication. 由于某些原因,我正在使用HTTP摘要式身份验证。 I've used the Flask-HTTPAuth library to implement the digest authentication and it works; 我已经使用了Flask-HTTPAuth库来实现摘要身份验证,并且它可以工作。 however, I am unable to authenticate in the unit tests. 但是,我无法在单元测试中进行身份验证。

For the unit tests, prior to setting up the authentication, I'm doing something like this: 对于单元测试,在设置身份验证之前,我正在执行以下操作:

class FooTestCase(unittest.TestCase):
    def setUp(self):
        self.app = foo.app.test_client()

    def test_root(self):
        response = self.app.get('/')
        # self.assert.... blah blah blah

Prior to implementing the authentication, this was fine. 在实施身份验证之前,这很好。 Now I get a 401, which is expected as the initial response for a digest auth request. 现在,我得到一个401,它应作为摘要auth请求的初始响应。 I've searched and searched and followed a few suggestions related to http basic auth (using parameters data = { #various stuff} and follow_redirects=True) but I've had no success. 我进行了搜索,并遵循了一些与http基本身份验证相关的建议(使用参数data = {#various stuff}和follow_redirects = True),但是我没有成功。

Does anyone have a clue how to implement unittests in this case? 在这种情况下,有谁知道如何实施单元测试?

Unfortunately digest authentication is harder to test or bypass in Flask-HTTPAuth. 不幸的是,摘要身份验证在Flask-HTTPAuth中难以测试或绕过。

One option is to actually calculate the correct hashes and perform the full authentication during tests. 一种选择是实际计算正确的哈希值并在测试过程中执行完整的身份验证。 You can see a few examples of this in the Flask-HTTPAuth unit tests . 您可以在Flask-HTTPAuth单元测试中看到一些示例。 Here is one: 这是一个:

def test_digest_auth_login_valid(self):
    response = self.client.get('/digest')
    self.assertTrue(response.status_code == 401)
    header = response.headers.get('WWW-Authenticate')
    auth_type, auth_info = header.split(None, 1)
    d = parse_dict_header(auth_info)

    a1 = 'john:' + d['realm'] + ':bye'
    ha1 = md5(a1).hexdigest()
    a2 = 'GET:/digest'
    ha2 = md5(a2).hexdigest()
    a3 = ha1 + ':' + d['nonce'] + ':' + ha2
    auth_response = md5(a3).hexdigest()

    response = self.client.get(
        '/digest', headers={
            'Authorization': 'Digest username="john",realm="{0}",'
                             'nonce="{1}",uri="/digest",response="{2}",'
                             'opaque="{3}"'.format(d['realm'],
                                                   d['nonce'],
                                                   auth_response,
                                                   d['opaque'])})
    self.assertEqual(response.data, b'digest_auth:john')

In this example, the username is john and the password is bye . 在此示例中,用户名是john ,密码是bye Presumably you have some predetermined credentials for a user that can be used in unit tests, so you would plug those in the a1 variable above. 大概您已经为用户提供了一些可以在单元测试中使用的预定凭据,因此您可以将这些凭据插入上面的a1变量中。 This authentication dance can be included in an auxiliary function that wraps the sending of a request during tests, that way you don't have to repeat this in every test. 身份验证动作可以包含在辅助功能中,该辅助功能在测试期间包装了请求的发送,因此您不必在每个测试中都重复此步骤。

It's not neccessary to use real-world authentication in tests. 在测试中不必使用真实身份验证。 Either disable authentication when running tests or create test user and use this test user in tests. 运行测试时禁用身份验证,或者创建测试用户并在测试中使用该测试用户。

For example: 例如:

    @digest_auth.get_password
    def get_pw(username):
        if running_from_tests():
            if username == 'test':
                return 'testpw'
            else:
                return None
        else:
            # ... normal auth that you have

Of couse this test user must never be active in production :) For implementation of running_from_tests() see Test if code is executed from within a py.test session (if you are using py.test). 当然,这个测试用户一定不能在生产环境中活跃:)有关running_from_tests()实现,请参阅测试代码是否在py.test会话中执行 (如果使用的是py.test)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM