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

How do I unit test HTTP Digest Authentication in Flask?

我有一个实现 REST api 的烧瓶应用程序。由于某些原因,我正在使用 HTTP 摘要身份验证。我已经使用 Flask-HTTPAuth 库来实现摘要身份验证并且它有效;但是,我无法在单元测试中进行身份验证。

对于单元测试,在设置身份验证之前,我正在做这样的事情:

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

在实施身份验证之前,这很好。现在我得到一个 401,这是对摘要授权请求的初始响应。我已经搜索和搜索并遵循了一些与 http 基本身份验证相关的建议(使用参数数据 = { #various stuff} 和 follow_redirects=True),但我没有成功。

有人知道如何在这种情况下实施单元测试吗?

没有必要在测试中使用真实世界的身份验证。在 运行 测试时禁用身份验证或创建测试用户并在测试中使用此测试用户。

例如:

    @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

当然,此测试用户绝不能在生产中处于活动状态 :) 有关 running_from_tests() 的实施,请参阅 Test if code is executed from within a py.test session(如果您使用的是 py.test)。

不幸的是,摘要式身份验证在 Flask-HTTPAuth 中更难测试或绕过。

一个选项是实际计算正确的哈希值并在测试期间执行完整的身份验证。您可以在 Flask-HTTPAuth unit tests 中看到一些这样的示例。这是一个:

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')

在这个例子中,用户名是john,密码是bye。假设您有一些预先确定的用户凭据,可以在单元测试中使用,因此您可以将这些凭据插入上面的 a1 变量中。这个身份验证舞蹈可以包含在一个辅助函数中,该函数在测试期间包装请求的发送,这样你就不必在每个测试中重复这个。