Аутентификация сервера единого входа в Ruby / Rack - PullRequest
15 голосов
/ 16 апреля 2011

Я пишу и размещаю веб-приложения на серверах Windows для использования в интрасети. Мой стек серверов использует Sinatra (который использует Rack), Thin и (в некоторых случаях) Apache только для обратного прокси.

Я хочу поддерживать единый вход (используя NTLM или Kerberos) в нашем домене, поддерживаемом ActiveDirectory. Я видел, что могу использовать mod_ntlm или mod_auth_kerb, когда я нахожусь за Apache, чтобы выполнить мою аутентификацию NTLM. Я еще не пробовал это, но я предполагаю, что это будет работать.

Мой вопрос касается аутентификации NTLM или Kerberos, когда я не отстаю от Apache, использую только Thin и Sinatra. Я видел rack-ntlm , но подробности использования там крайне скудны.

Пожалуйста, предоставьте известный рабочий код под Sinatra или Rack, который показывает, как использовать NTLM или Kerberos на стороне сервера , аутентификацию с ActiveDirectory (предположительно через net-ldap).

Редактировать : Подчеркнул желаемые ответы, так как до сих пор нет ответов, дающих явную помощь по этому вопросу. Пользователи должны иметь возможность найти этот ответ и иметь рабочее решение, а не указатели на внешние библиотеки, которые они должны выяснить, как их использовать.

Ответы [ 6 ]

9 голосов
/ 09 апреля 2012

Я написал Rack::Auth модуль, который реализует единый вход NTLM.Это может быть немного грубо, но это работает для меня.Он выполняет все те вопросы, требующие ответа / ответа, которые требуются для NTLM, и устанавливает REMOTE_USER на то, что отправил браузер.

Вот код.

Чтобы это работало,браузер должен быть настроен на отправку файлов NTLM на сервер.В моей среде это происходило только тогда, когда адрес сервера был в списке доверенных доменов.Для Firefox домен должен быть добавлен в список, назначенный ключу network.automatic-ntlm-auth.trusted-uris, к которому можно получить доступ через about:config.

7 голосов
/ 27 апреля 2011

Хотя у меня нет кода для совместного использования и нет сервера AD для тестирования, я опубликую некоторую общую информацию, которая может оказаться полезной для других при использовании rack-ntlm (это был бы лучший маршрут приэтот момент).

Первое, что нужно понять, это то, что NTLM фактически никогда не дает вам пароль пользователя.Вам не нужно аутентифицировать пользователя внутри вашего приложения.NTLM уже сделал это.Rack-ntlm предоставит вам домен + пользователя, с которым вы затем сможете работать.

rack-ntlm выполняет дополнительную работу с этой информацией, которая может быть полезной для вас, а может и не иметь.Вы предоставляете ему сервер AD, порт и набор учетных данных.Он возьмет этот пользовательский объект (из-за отсутствия лучшего слова) и найдет его в AD с помощью вызова LDAP.

Учетные данные, которые Rack-Ntlm запрашивает в настройках, будут ВАШИМИ учетными данными (или оптимально).учетные данные для конкретного приложения в домене с ограниченным доступом к запросам).С помощью этого запроса вы получите сведения об этом пользователе из AD (членство в группах, адреса электронной почты и т. Д.).Вы можете использовать это для дальнейшего заполнения вашей базы данных данными пользователя.

Следует отметить, что если вы используете какой-либо браузер ДРУГОЕ, чем IE (а в некоторых случаях даже с IE), ваши пользователи получатдиалог аутентификации HTTP.В зависимости от того, находится ли ваш сайт во внутренней сети или нет, IE автоматически пройдет учетные данные NTLM.Это контролируется для каждого браузера, поэтому вы можете не иметь никакого контроля.В Firefox есть параметр about: config, который позволит вам заполнять доверенные сайты.

Так что, если мы вернемся к rack-ntlm, поток будет выглядеть примерно так:

  • browser -> sinatra app
  • (здесь работает вызов / ответ
    handwaving)
  • rack-ntlm теперь ищет пользователя в AD через LDAP
  • sinatraПриложение теперь содержит данные о пользователях из LDAP в некоторых хэшах
  • . Приложение sinatra создает базового пользователя
  • для хранения имени пользователя (без пароля
    , потому что у вас его нет) с некоторым базовым набором способностей.в локальном хранилище данных
  • sinatra устанавливает cookie для "входа в систему" или чего-либо еще

Если вы хотите, вы можете сопоставить группы AD с ролями приложений в некоторой емкости, например, для доменаАдминистраторы автоматически были добавлены в вашу роль администратора.

2 голосов
/ 18 июля 2013

Есть люди, отвечающие на этот вопрос об аутентификации / безопасности, которые дают совершенно ложную и вводящую в заблуждение информацию, которая потенциально очень опасна.NTLM - это двухфазный процесс.У вас есть согласование между клиентом и веб-сервером, которое получает подробности от клиента, такие как предполагаемое имя пользователя и токен, который зашифрован с помощью хэша пароля пользователя.Многие люди думают, что пока вы можете общаться NTLM с клиентом, каким-то образом произошла аутентификация.Я понятия не имею, почему люди делают это предположение, возможно, потому что процесс рукопожатия NTLM относительно запутан.

Если вы останавливаетесь после первого этапа и не выполняете фактическую аутентификацию, вы доверяете клиенту/ user, в этом случае вы также можете не выполнять какую-либо аутентификацию и просто поместить сообщение «Пожалуйста, не используйте это веб-приложение, если вам не разрешено».

Второй этап - это фактическийаутентификация.Веб-сервер отправляет сведения, предоставленные клиентом (зашифрованный токен) контроллеру домена.Контроллер домена знает хэш пароля пользователя, использованного для шифрования токена, и, таким образом, выполняет такое же шифрование хэша пароля.Если это соответствует значению клиента, то мы знаем, что клиент использовал правильный хэш пароля.Веб-сервер никогда не видит хешированный пароль, он видит только токен, зашифрованный хешированным паролем, в качестве ключа шифрования.

К сожалению, не так много библиотек LDAP, которые поддерживают возможности NETLOGON, необходимые для подлинной аутентификацииТокен NTLM, вероятно, потому, что это нетривиальная фирменная хрень.Samba (ну, на самом деле winbind) - одна из немногих библиотек, которая может это сделать.В настоящее время нет библиотеки Ruby, способной к аутентификации NTLM, хотя есть много библиотек, которые сообщат вам имя пользователя, сообщаемое клиентом, хотя клиент может сообщить любое имя пользователя, которое ему нравится.

Как правило,Большой палец, если ваша библиотека NTLM не запрашивает информацию о вашем контроллере домена, то нет никакой возможности выполнить какую-либо аутентификацию.Многие разработчики этих простых библиотек сами не знают, что делают.

1 голос
/ 23 апреля 2011

Я успешно использовал модуль Apache Kerberos, о котором вы упомянули (http://modauthkerb.sourceforge.net/) Затем он представляет тот же API, что и базовая аутентификация, и предоставляет все полезные функции Kerberos. Вам просто нужно использовать простой Rack :: Auth:: Basic, и все.

Для простой аутентификации в Rack вы, вероятно, могли бы использовать https://github.com/djberg96/rack-auth-kerberos,, но я лично не пробовал это сделать. Однако код выглядит прямо вперед.

Очевидно, что в обоих случаях вам придется представить свой сервер в AD.

1 голос
/ 16 апреля 2011

Я использую OmniAuth , чтобы выполнить аутентификацию на основе интерфейса ActiveDirectory LDAP. Документация довольно хорошая, и она легко подключается к Rack.

0 голосов
/ 23 января 2018

У меня это работает без стоек и решений NTLM.

Для проверки подлинности посмотрите мой ответ здесь: есть ли способ прочитать имя пользователя Windows для входа в систему, используя ruby ​​on rails

Затем авторизацию можно выполнить с помощью гема net-ldap, проверив членство в группах безопасности.

Это выполняется только один раз, когда запускается сервер / служба, но недостатком является необходимость перезапуска службы.когда участники в группе меняются.Конечно, вы можете хранить авторизованных пользователей в таблице базы данных.

Вот мой код.

В приложении Sinatra

require 'net-ldap'

HOST     =   "XXXXXX"
PORT     =   389
LDAP = Net::LDAP.new(:host => HOST, :port => PORT)

# get account info somewhere safe
LDAP.auth(CONFIG.admin_user, CONFIG.admin_password)

if LDAP.bind
  log "ldap logged in"
else
  log "ldap login failed"
  abort
end

# CONFIG.permitted_users is the name of the apps security group
$members = get_members CONFIG.permitted_users

и в файле помощника

def get_ldap_username cn
  treebase = "ou=xxxxxx,ou=xxxxxx,ou=xxxxxxx,ou=xxxxxx,dc=xxx,dc=xx"
  filter = Net::LDAP::Filter.eq("cn", cn)
  LDAP.search(:filter => filter, :base => treebase) do |item| 
    return item.sAMAccountName.first
  end
end

def get_members name, members = []
  treebase = "ou=xxxxxxx,ou=xxxxxxx,ou=xxxxxxx,ou=xxxxxx,dc=xxx,dc=xx"
  filter = Net::LDAP::Filter.eq("cn", name)
  LDAP.search(:filter => filter, :base => treebase) do |item| 
    item.each do |attribute, values|
      if attribute == :member
        values.each do |value|
          cn = value[/CN=([^,]+),/,1]

          # my groups all begin with a letter/number sequence
          # recurse this method if member is a group itself
          if cn[0..2].downcase == "xxx" # xxx something else of course
            get_members cn, members
          else
            members << get_ldap_username(cn)
          end

        end
      end
     end
  end
  members # an array of permitted usernames
end

before do
  # authentication code 
  # see /4390686/est-li-sposob-prochitat-imya-polzovatelya-windows-ispolzuya-ruby-na-relsah

  # authorisation
  unless $members.include? @username
    halt "No access"
  end
end
...