为什么在与Sinatra应用程序中的默认GET和POST登录路由以及401处理相结合时,Rack中间件无法重定向?
相关的Shield中间件提取:
module Shield
class Middleware
attr :url
def initialize(app, url = "/login")
@app = app
@url = url
end
def call(env)
tuple = @app.call(env)
if tuple[0] == 401
[302, headers(env["SCRIPT_NAME"] + env["PATH_INFO"]), []]
else
tuple
end
end
private
def headers(path)
{ "Location" => "%s?return=%s" % [url, encode(path)],
"Content-Type" => "text/html",
"Content-Length" => "0"
}
end
def encode(str)
URI.encode_www_form_component(str)
end
end
end
查看full source code(104行/2.8kb)。
这是Sinatra应用程序的相关摘录:
# application_controller.rb
class ApplicationController < Sinatra::Base
helpers Shield::Helpers
use Shield::Middleware, "/login"
...
get '/noway' do
error(401) unless authenticated(User)
erb :app_noway
end
get '/login' do
erb :login
end
post "/login" do
if login(User, params[:login], params[:password])
remember(authenticated(User)) if params[:remember_me]
redirect(params[:return] || "/")
else
redirect "/login"
end
end
end
完整源代码(显示问题行为的基本应用),方便快捷查看:https://github.com/shieldtest/shieldtest
存储库已准备好进行克隆和机架式处理。与数据库,环境和所有。登录信息;电子邮件:shield@example.org,密码:shield。
问题
当访问受保护的路由(/ noway)时,中间件会按预期注入身份验证过程。但在成功进行身份验证后,后续重定向始终默认为root,而不是受保护页面的返回URL(/ noway)。
需要解决方案
通过Shield成功验证后,受保护的页面(/ noway)应自动重定向到。
<小时/> 直观漫游
第1步(下方):在Sinatra主页上。点击链接到受保护页面(/ noway)
步骤2(如下):正确地重定向到/ login,因为没有用户通过身份验证。正确输入正确的登录凭据
问题行为 - 重定向到主页而不是受保护的页面步骤3A(下方):输入正确的登录凭据后:再次发送回主页(再次)
测试登录 - 现在可以访问受保护的页面(手动,再次点击页面)
步骤4(下面):在主页面上。再次点击受保护的页面(/ noway)=&gt;授予访问权限
答案 0 :(得分:0)
似乎params[:return]
从未转发到POST请求。
因此,'脏修复'将获取返回参数并通过登录表单将其传递给POST请求。这会产生所需的行为:
#login.rb
...
<% if params[:return] %>
<input type='hidden' name='redirect' value="<%= params[:return] %>">
<% end %>
...
然后从登录表单重定向到重定向参数:
#application_controller.rb
post "/login" do
if login(User, params[:login], params[:password])
...
redirect to params[:redirect] || "/"
...
end
end
尽管如此,我还是希望了解为什么中间件没有按预期执行,以及如何通过Rack中间件修复/存储此返回参数。