Разработать несанкционированный 401 После входа

#ruby-on-rails #devise

#ruby-on-rails #разработка

Вопрос:

Я использую rails 4.1.2 и devise 3.2.4

Я видел, как этот вопрос задавался ранее, и просматривал Интернет в поисках решения, но все рекомендации не работают. После успешного входа (для участника увеличен sign_in_count, метод current_member возвращает правильный участник), разработайте маршруты обратно на исходную страницу, которую участник пытался просмотреть, но

 Completed 401 Unauthorized in 2ms
  

результат всегда есть, и участник перенаправляется обратно на страницу входа (сеансы #новые)

В моем макете есть мета-теги CSRF.

Я попытался определить маршруты, которые я хочу аутентифицировать:

 devise_for :members, :path => '/' # i want sign in path to be /sign_in

devise_scope: :members do
  root 'application#index'
  get 'car_wash/:dealer_id', to: 'car_wash#show'
  post 'car_wash/:id/update', to: 'car_wash#update'
end
  

В контроллерах я хочу пройти аутентификацию:

 before_filter :authenticate_member!
  

В модели участников

 devise :database_authenticatable, :authenticatable, :rememberable, :trackable, :authentication_keys => [ :username ]
  

Журнал выглядит следующим образом:

 12:26:34 web.1         | Started POST "/sign_in" for 127.0.0.1 at 2014-07-02 12:26:34 -0500
12:26:34 web.1         | Processing by Members::SessionsController#create as HTML
12:26:34 web.1         |   Parameters: {"utf8"=>"✓","authenticity_token"=>"4tQIel82ktomEwfsvkgXzB7XfXJlmJxmlea9BnjaIYk=", "member"=>{"username"=>"John", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Sign in"}
12:26:34 web.1         |   Member Load (0.5ms)  SELECT  "members".* FROM "members"  WHERE "members"."username" = 'John' LIMIT 1
12:26:35 web.1         |    (0.3ms)  BEGIN
12:26:35 web.1         |    (0.3ms)  COMMIT
12:26:35 web.1         |    (0.2ms)  BEGIN
12:26:35 web.1         |   SQL (0.5ms)  UPDATE "members" SET "current_sign_in_at" = $1, "last_sign_in_at" = $2, "sign_in_count" = $3, "updated_at" = $4 WHERE "members"."id" = 1  [["current_sign_in_at", "2014-07-02 17:26:35.878880"], ["last_sign_in_at", "2014-07-02 17:23:42.608524"], ["sign_in_count", 23], ["updated_at", "2014-07-02 17:26:35.879614"]]
12:26:35 web.1         |    (6.3ms)  COMMIT
12:26:35 web.1         | Redirected to http://localhost:3000/
12:26:35 web.1         | Completed 302 Found in 1408ms (ActiveRecord: 8.6ms)
12:26:35 web.1         |
12:26:35 web.1         |
12:26:35 web.1         | Started GET "/" for 127.0.0.1 at 2014-07-02 12:26:35 -0500
12:26:35 web.1         | Processing by ApplicationController#index as HTML
12:26:35 web.1         | Completed 401 Unauthorized in 2ms
12:26:35 web.1         |
12:26:35 web.1         |
12:26:35 web.1         | Started GET "/sign_in" for 127.0.0.1 at 2014-07-02 12:26:35 -0500
12:26:35 web.1         | Processing by Members::SessionsController#new as HTML
12:26:35 web.1         |   Rendered devise/shared/_links.erb (0.1ms)
12:26:35 web.1         |   Rendered devise/sessions/new.html.erb within layouts/application (4.2ms)
12:26:35 web.1         |   Rendered shared/_header.html.haml (1.5ms)
12:26:35 web.1         | Completed 200 OK in 24ms (Views: 21.2ms | ActiveRecord: 1.0ms)
  

Я использую пользовательскую стратегию warden для определения успеха или неудачи аутентификации на основе вызова внешнего API. Я прошел через каждую часть этой логики, и она отлично работает!

 # config/initializers/devise.rb
config.warden do |manager|
  manager.intercept_401 = false
  manager.default_strategies(:scope => :member).unshift :member_login
end
  

Но по какой-то причине успешный вход не зависает.

РЕДАКТИРОВАТЬ: найдено решение. Проблема заключалась в моей пользовательской стратегии аутентификации Warden (большой сюрприз):

 Warden::Strategies.add(:member_login) do
  def member_params
    ActionController::Parameters.new(@response).permit(:first_name, :last_name, :role, :username, :external_api_user_id)
  end

  def valid?
    params[:member] amp;amp; ( params[:member][:username] || params[:member][:password] )
  end

  def authenticate!
    member = Member.find_by_username(params[:member][:username])
    if authenticate_with_ppd_api
      if member
        member.update(member_params)
        success!(member)
      else
        member = Member.create(member_params)
        success!(member)
      end
    else
      fail!("Incorrect username or password")
    end
  end

  def authenticate_with_api
    @response = HTTParty.post('https://path.to.server/admin/login', body: { username: params[:member][:username], password: params[:member][:password] } )
    @response = JSON.parse(@response.body).first
    @response["authenticated"]
  end

end
  

Я не разрешал ‘authenticity_token’ для участника. После добавления этого, вход работает:

 ActionController::Parameters.new(@response).permit(:authenticity_token, :first_name, :last_name, :role, :username, :external_api_user_id)
  

Это все еще очень сбивает меня с толку. Я только обновлял / создавал пользователя для своих собственных целей, а не для чего-либо, связанного с аутентификацией. Я понятия не имею, почему обновление токена подлинности не происходит автоматически. Это могло бы помочь, если бы я знал, что делает стратегия Warden по умолчанию. Ну что ж. По крайней мере, это работает.

РЕДАКТИРОВАТЬ: О боже! Что ж, вход работает, но выход — нет! Это «исправление» делает возможным вход в систему, но не выход. Отправка запроса на УДАЛЕНИЕ в /sign_out абсолютно ничего не дает. Вернуться к исходной точке 1