从中间件中触发基本的HTTP身份validation

我已经为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窗口的方法 。 我对此进行了审核,并没有看到任何明显的迹象表明这是如何完成的。

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

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

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

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

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

我直接使用Rack::Auth::Basic并保存自己的validation部分:

 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 

“`

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

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

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