Как развернуть несколько приложений Rack / Sinatra с Passenger (на Apache) с базовой аутентификацией HTTP? - PullRequest
4 голосов
/ 12 февраля 2012

Проблема здесь в том, что несколько экземпляров одного и того же приложения Sinatra (Rack), развернутого в Passenger + Apache, на разных подчиненных URI с базовой аутентификацией HTTP для защиты от нежелательного доступа:

У меня есть 4 экземпляра приложения Sinatra, развернутых в моем домене как:

  1. example.com/private/foo
  2. example.com/private/moo
  3. ...
  4. ...

Доступ ко всем из них защищен базовой аутентификацией HTTP с использованием промежуточного программного обеспечения Rack::Auth::Basic. config.ru все они выглядят так:

# ...
users = {'user' => 'password'}
use Rack::Auth::Basic, 'realm' do |username, password|
    users.key?(username) && users[username] == password
end

run MyApp

Единственное, что меняется от одного config.ru к другому, - это параметр 'realm'.

Теперь проблема в том, что после входа в одно из приложений, скажем, private/foo, Chrome не запрашивает у меня имя пользователя и пароль для других приложений (private/moo и т. Д.). Это нелогично, поскольку все экземпляры однозначно идентифицируются по их URL. Использование разных учетных данных для каждого экземпляра работает, но не должен ли Chrome запрашивать учетные данные хотя бы один раз для каждого экземпляра? Одна вещь, которую я заметил, заключается в том, что при первом входе в один из экземпляров Chrome говорит: «Серверу на example.com:80 требуется имя пользователя и пароль». Я бы ожидал, что «ресурс example.com/private/foo требует имя пользователя и пароль». Разве это не так, как это должно работать?

Я проверил Rack::Auth::Basic исходный код и статью Википедии о Базовая аутентификация HTTP и не нашел ничего, что могло бы помочь в моем случае: (.

1 Ответ

2 голосов
/ 13 мая 2012

При базовой аутентификации параметр области не отправляется обратно на сервер. Таким образом, сервер не может действительно проверить, отправляет ли клиент заголовок авторизации для той же области или нет. Это зависит от клиента. Реализация базовой аутентификации HTTP в Rack верна. Итак:

Теперь проблема в том, что после того, как я вошел в одно из приложений, скажем, private / foo, Chrome не запрашивает у меня имя пользователя и пароль для других приложений (private / moo и т. Д.). Это нелогично, поскольку все экземпляры однозначно идентифицируются по их URL.

Как отметил Эндрю, и это ясно из RFC, URL здесь не играет роли. Но если '/ foo' защищен, '/ foo / moo' защищен в той же области.

Использование разных учетных данных для каждого экземпляра работает, но разве Chrome не должен запрашивать учетные данные хотя бы один раз для каждого экземпляра?

В некоторых случаях (при проверке с помощью инструментов отладчика) после того, как я вошел в одно из приложений, скажем private / foo, Chrome повторно отправляет тот же заголовок авторизации другим приложениям, скажем private / Му, не оспаривая в первую очередь.

В RFC говорится, что клиент может отправить соответствующий заголовок авторизации для области без предварительной проверки сервером.

Похоже, что Chrome либо обрабатывает все мои приложения в одной области, либо повторно отправляет один и тот же заголовок авторизации в разные области. Я не думаю, что это ожидаемое поведение, но я мог что-то упустить. Firefox ведет себя так же. Во всяком случае, это не суть вопроса.

Тема вопроса была «Как заставить Chrome запрашивать у меня имя пользователя и пароль хотя бы один раз для каждого экземпляра? Базовая аутентификация не работает так, как я ожидал; почему?»

Использовать дайджест-проверку подлинности (снова RFC 2617). В стойке реализована версия алгоритма MD5 под Rack::Auth::Digest::MD5. Установите разные opaque для каждого экземпляра, и все готово:

# ...
realm  = "Description of the protected area."
opaque = "Secret key that uniquely identifies a realm."

users = {'user' => 'password'}
use Rack::Auth::Digest::MD5, realm, opaque do |username|
  users[username]
end

opaque отправляется обратно клиентом, и на стороне сервера можно проверить, что запрос на авторизацию предназначен для правильного ресурса. Работа realm кажется дескриптивной по своей природе - какую область или ресурс вы пытаетесь защитить? какой идентификатор мне прошить?

RFC: http://tools.ietf.org/html/rfc2617

...