Rack междинният софтуер не успява да пренасочи при удостоверяване в Sinatra

Защо мидълуерът на Rack не успява да пренасочи, когато е съчетан с маршрутите за влизане по подразбиране GET и POST и обработката на 401 в приложението Sinatra?

Съответен екстракт от мидълуер на 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

Вижте пълния изходен код (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

Хранилището е готово за „клониране и събиране“ с база данни, env и всичко останало. Идентификационни данни за вход; имейл: [email protected], парола: shield.

Проблем
При достъп до защитен маршрут (/noway), междинният софтуер инжектира процес на удостоверяване, както е предвидено. Но след успешното удостоверяване, последващото пренасочване винаги се задава по подразбиране на root, вместо URL адреса за връщане за защитената страница (/noway).

Необходимо решение
Защитената страница (/noway) трябва да бъде пренасочена автоматично след успешно удостоверяване чрез Shield.


Визуална разходка

Стъпка 1 (по-долу): На главната страница на Синатра. Щракнете върху връзка към защитена страница (/noway) въведете описание на изображението тук

Стъпка 2 (по-долу): Правилно пренасочен към /login, тъй като нито един потребител не е удостоверен. Въведете правилно правилните идентификационни данни за вход.
въведете описание на изображението тук

ПРОБЛЕМНО ПОВЕДЕНИЕ - пренасочено към главната вместо към защитената страница
Стъпка 3A (по-долу): След въвеждане на правилни идентификационни данни за вход: изпратено обратно към главната страница (отново)
въведете описание на изображението тук

ТЕСТВАНЕ НА ВХОД - защитената страница е достъпна сега (ръчно, чрез повторно щракване върху страницата)
Стъпка 4 (по-долу): На главната страница. Щракнете отново върху защитената страница (/noway) => Достъпът е предоставен въведете описание на изображението тук


person Frank    schedule 20.03.2015    source източник


Отговори (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.

person Frank    schedule 31.03.2015