从中间件中触发基本HTTP身份验证

时间:2013-05-16 00:27:23

标签: ruby-on-rails ruby authentication rack middleware

我为rails创建了一个自定义中间件,它将拦截所有请求,并确保它来自授权的IP,否则它应该提示基本的http auth用户/名称密码。

目前看来是这样的:

require 'net/http'

class AuthorizeEnvironment
  def initialize(app)
    @app = app
  end

  def call(env)
    if AppConstants.approved_doximity_ips.include?(env["REMOTE_ADDR"])
      @app.call(env)
    elsif authorized?(env)
      @app.call(env)
    else
      [403, {"Content-Type" => "text/html"}, ["Not Authorized on this environment."]]
    end
  end

  def authorized?(env)
    @auth ||= Rack::Auth::Basic::Request.new(env)
    @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == ['username', 'password']
  end
end

此代码的问题是我似乎无法找到触发浏览器上的http auth窗口的方法。我查看了this并没有看到任何明显的迹象表明这是如何完成的。

你能指点我正确的方向吗?

3 个答案:

答案 0 :(得分:2)

我直接使用Rack::Auth::Basic并自行保存验证部分:

class BasicAuth
  def initialize(app)
    @app = app
  end

  def call(env)
    if env["PATH_INFO"] == '/supersecret' # Any condition here
      auth = Rack::Auth::Basic.new(@app) do |u, p|
        u == username && p == password
      end
      auth.call env
    else
      @app.call env
    end
  end

  def username
    ENV["username"]
  end

  def password
    ENV["password"]
  end
end

```

答案 1 :(得分:1)

我没有测试过您的代码,但看起来您的回复是403,意思是“禁止”。即,当前登录的用户无权访问此资源。

来自RFC(http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

  

服务器理解请求,但拒绝履行请求。授权无效,请求不应重复。如果请求方法不是HEAD并且服务器希望公开为什么请求没有得到满足,那么它应该描述实体中拒绝的原因。如果服务器不希望将此信息提供给客户端,则可以使用状态代码404(未找到)。

相反,您需要使用401,并且只有当前登录的用户无法访问资源时才会回复403.

答案 2 :(得分:1)

您需要提供WWW-Authenticate标头。 See

我认为,在你的else中,你会这样做:

[401, {'WWW-Authenticate' => 'Basic realm="Application"', "Content-Type" => "text/html"}, ["Not Authorized on this environment."]]