【问题标题】:Rack middleware fails to redirect on authentication in Sinatra机架中间件无法重定向 Sinatra 中的身份验证
【发布时间】:2015-05-23 16:35:46
【问题描述】:

为什么 Rack 中间件在与 Sinatra 应用程序中的默认 GET 和 POST 登录路由以及 401 处理结合使用时无法重定向?

相关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) => 授予访问权限

【问题讨论】:

    标签: authentication sinatra rack middleware


    【解决方案1】:

    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 中间件修复/存储此返回参数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-10
      • 1970-01-01
      • 2022-01-24
      • 2018-02-22
      • 2011-03-29
      • 2012-04-12
      • 1970-01-01
      • 2019-01-25
      相关资源
      最近更新 更多