ruby - 如何使用带有 HTTP 基本身份验证的 Passenger(在 Apache 上)部署多个 Rack/Sinatra 应用程序?

标签 ruby sinatra passenger rack

这里的问题是同一 Sinatra (Rack) 应用程序的多个实例部署在 Passenger+Apache 上的不同子 URI 上,使用 HTTP 基本身份验证来阻止不需要的访问:

我在我的域中部署了 4 个 Sinatra 应用实例:

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

使用 Rack::Auth::Basic 中间件通过 HTTP 基本身份验证保护对它们的访问。 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 Basic Auth 的文章并没有想出任何可以帮助我的案子:(。

最佳答案

在基本身份验证中,realm 参数不会发送回服务器。所以服务器无法真正检查客户端是否正在为同一领域发送授权 header 。这取决于客户。 Rack 对 HTTP 基本身份验证的实现是正确的。所以:

Now the issue is that once I have logged into one of the apps, say private/foo, Chrome doesn't prompt me for a username and password for other apps (private/moo etc.). This is counterintuitive since all instances are uniquiely identified by their URLs.

正如 Andrew 指出并从 RFC 中明确指出的那样,URL 在那里不起作用。但是,如果 '/foo' 受到保护,则 '/foo/moo' 也受到同一领域的保护。

Using different credentials for each instance does work, but shouldn't Chrome request credentials at least once for each instance?

在幕后发生的事情(在使用调试器工具检查时)是,在我登录到其中一个应用程序后,比如 private/foo,Chrome 将相同的授权 header 重新发送到其他应用程序,比如 private/哞哞叫,没有先被挑战。

RFC 说客户端可以发送一个域的相应授权 header ,而无需首先受到服务器的质询。

看起来 Chrome 要么将我的所有应用程序视为同一领域,要么在不同领域重新发送相同的授权 header 。我不认为这是预期的行为,但我可能会遗漏一些东西。 Firefox 的行为相同。无论如何,这不是问题的本质。

问题的主题是“我如何让 Chrome 为每个实例至少请求一次用户名和密码?基本身份验证没有按我预期的方式工作;为什么?”

使用摘要式身份验证(再次使用 RFC 2617)。 Rack在Rack::Auth::Digest::MD5下实现了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 的工作本质上似乎是描述性的——您要保护哪个区域或资源?我刷什么id?

RFC:https://www.rfc-editor.org/rfc/rfc2617

关于ruby - 如何使用带有 HTTP 基本身份验证的 Passenger(在 Apache 上)部署多个 Rack/Sinatra 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9251704/

相关文章:

sinatra - 没有此类文件可加载 Passenger 和 Sinatra

deployment - 使用 capistrano + Nginx +Passenger + MYSQL 部署 Rails 到 VPS

ruby-on-rails - 如果变量为 nil 则分配字符串,否则附加

ruby-on-rails - 在 ruby​​ 中执行二进制文件(在 Heroku 上)

mysql - DataMapper 无内存错误 - Sinatra

ruby-on-rails - 找不到 JavaScript 运行时。有关可用运行时列表,请参阅 https ://github. com/sstephenson/execjs

ruby-on-rails - Ruby/Rails Apache2 和 Passenger 设置返回目录列表

Ruby 与法拉第 stub ,无法让它工作

ruby - 对 Ruby 数组进行排序 - 失败,出现 TypeError : can't convert Symbol into Integer

ruby-on-rails - 精简 EventMachine Sinatra 与 Rails