2

У меня есть флеш-приложение, которое реализует REST api. По причинам, я использую HTTP Digest Authentication. Я использовал библиотеку Flask-HTTPAuth для реализации аутентификации дайджеста, и она работает; однако я не могу пройти аутентификацию в модульных тестах.Как выполнить модульную проверку подлинности HTTP-дайджеста в фляге?

Для модульных тестов, до настройки проверки подлинности, я делаю что-то вроде этого:

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, который ожидается как начальный ответ для запроса autest. Я искал и искал и следил за несколькими предложениями, связанными с http basic auth (используя параметры data = {#various stuff} и follow_redirects = True), но я не имел успеха.

Кто-нибудь знает, как реализовать unittests в этом случае?

ответ

3

К сожалению, аутентификация дайджеста сложнее проверить или обойти в 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 выше. Этот танец аутентификации может быть включен во вспомогательную функцию, которая обертывает отправку запроса во время тестов, так что вам не нужно повторять это в каждом тесте.

+0

Yup. Мне нужно сделать запрос, получить 401, построить заголовки дайджеста auth на основе возврата (который я могу найти в объекте ответа в pycharm). Так же, как код, который вы скопировали и вставили, делает ... На деньги, спасибо. –

0

В испытаниях не обязательно использовать аутентификацию в реальном времени. Либо отключите аутентификацию при выполнении тестов, либо создайте тестового пользователя, и используйте этот тестовый пользователь в тестах.

Например:

@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).

+0

Спасибо за ответ. Я настроен на настройку тестового пользователя и получение пароля. Я могу сделать это прямо из БД. Моя проблема связана с функцией test_client(). Get(). Если бы я запускать сервер опоки, а затем из другой функции питона, если бы я использовал библиотеку запросов, я могу сделать что-то вроде этого: из requests.auth импорта HTTPDigestAuth результата = requests.get ('http://127.0.0.1:5000/', auth = HTTPDigestAuth ('test', 'mytestpw')) Это будет использовать дайджест, настроенный на сервере, для входа в систему. Но как мне сделать этот процесс в test_client(). Get()? –

+0

Извините, просто просмотрел форматирование в комментариях. Код сверху, если не ясно: 'от requests.auth импорта HTTPDigestAuth результат = requests.get ('127.0.0.1:5000/' AUTH = HTTPDigestAuth ('тест', 'mytestpw'))' –

+1

@ MikeLane Возможно, это: https://gist.github.com/jarus/1160696 – Messa