【问题标题】:Using Basic HTTP access authentication in Django testing framework在 Django 测试框架中使用 Basic HTTP 访问认证
【发布时间】:2011-07-26 14:40:13
【问题描述】:

对于我的一些 Django 视图,我创建了一个装饰器来执行基本 HTTP 访问身份验证。然而,在 Django 中编写测试用例时,我花了一段时间才弄清楚如何对视图进行身份验证。这就是我的做法。我希望有人觉得这很有用。

【问题讨论】:

    标签: python django unit-testing http-authentication django-testing


    【解决方案1】:

    对于 python3,您可以对 username:password 字符串进行 base64 编码:

    base64.b64encode(b'username:password')
    

    这会返回字节,因此您需要将其转换为带有.decode('ascii') 的ASCII 字符串:

    完整示例:

    import base64
    
    from django.test import TestCase
    
    class TestClass(TestCase):
       def test_authorized(self):
           headers = {
               'HTTP_AUTHORIZATION': 'Basic ' + 
                    base64.b64encode(b'username:password').decode("ascii")
           }
           response = self.client.get('/', **headers)
           self.assertEqual(response.status_code, 200)
    

    【讨论】:

    • 感谢您的回答。太有帮助了。
    【解决方案2】:

    (python3) 我在测试中使用这个:

    credentials_string = '%s:%s' % ('invalid', 'invalid')
    credentials = base64.b64encode(credentials_string.encode())
    self.client.defaults['HTTP_AUTHORIZATION'] = 'Basic ' + credentials.decode()
    

    以及以下视图:

    import base64
    [...]
    type, auth = request.META['HTTP_AUTHORIZATION'].split(' ', 1)
    auth = base64.b64decode(auth.strip()).decode()
    

    【讨论】:

      【解决方案3】:

      另一种方法是绕过 Django Client() 并改用 Requests。

      class MyTest(TestCase):
          def setUp(self):
              AUTH = requests.auth.HTTPBasicAuth("username", "password")
      
          def some_test(self):
              resp = requests.get(BASE_URL + 'endpoint/', auth=AUTH)
              self.assertEqual(resp.status_code, 200)
      

      【讨论】:

      • requests 的响应类不能保证与 django 使用的类 100% 兼容。例如,您将没有可用的response.context
      • 这会在网络上发出一个实际的 http 请求。这几乎不是您在单元测试中想要做的。
      【解决方案4】:

      在您的 Django TestCase 中,您可以更新客户端默认值以包含您的 HTTP 基本身份验证凭据。

      import base64
      from django.test import TestCase
      
      class TestMyStuff(TestCase):
      
          def setUp(self):
              credentials = base64.b64encode('username:password')
              self.client.defaults['HTTP_AUTHORIZATION'] = 'Basic ' + credentials
      

      【讨论】:

      【解决方案5】:

      我是这样做的:

      from django.test import Client
      import base64
      auth_headers = {
          'HTTP_AUTHORIZATION': 'Basic ' + base64.b64encode('username:password'),
      }
      c = Client()
      response = c.get('/my-protected-url/', **auth_headers)
      

      注意:您还需要创建一个用户。

      【讨论】:

      • 如果您正在处理 unicode 字符串(典型的例如:使用 py3),您需要执行类似 base64.b64encode('username:password'.encode()).decode() 的操作,因为 base64 模块不处理 unicode 字符串。
      • @Jocelyndelalande 更像base64.b64encode(bytes('username:password', 'utf8')).decode('utf8'),
      • 很好的答案!只是补充:使用python 3.5我刚刚制作了c.get('/my-protected-url/', HTTP_AUTHORIZATION='Basic username:password'),如django docsCGI docs所示。
      • 为什么是 HTTP_AUTHORIZATION 而不是授权?
      • @DanielGomezRico:确实令人困惑。有点晚了,不过可以在stackoverflow.com/q/15113248找到解释
      【解决方案6】:

      假设我有一个登录表单,我使用以下技术通过测试框架登录:

          client = Client()
          client.post('/login/', {'username': 'john.smith', 'password': 'secret'})
      

      然后我在其他测试中携带client,因为它已经过身份验证。你对这篇文章有什么问题?

      【讨论】:

      • 是的,这是一个很好的解决方案蒂埃里。虽然它不适用于 HTTP 授权,因为它通过将登录信用作为 HTTP 标头发送来工作。我这样做是因为视图是 API 调用而不是常规视图。
      猜你喜欢
      • 2015-03-29
      • 1970-01-01
      • 1970-01-01
      • 2012-02-29
      • 1970-01-01
      • 2017-10-11
      • 2015-04-19
      • 1970-01-01
      相关资源
      最近更新 更多