Чего мне не хватает для аутентификации пользователя с помощью Devise и JWT в Rails 5? - PullRequest
0 голосов
/ 26 апреля 2018

Я следовал этому руководству, чтобы настроить аутентификацию с помощью JWT, и разработал https://www.sitepoint.com/introduction-to-using-jwt-in-rails/. Мой аутентификационный_контроллер выглядит так:

class AuthenticationController < ApplicationController
  def authenticate_user
    user = User.find_for_database_authentication(email: params[:email])
    if user.valid_password?(params[:password])
      render json: payload(user) 
    else
      render json: {errors: ['Invalid Username/Password']}, status: 
:unauthorized
    end
  end

  private

  def payload(user)
    return nil unless user && user.id
    {
      auth_token: JsonWebToken.encode({user_id: user.id}),
      user: {id: user.id, email: user.email}
    }
  end
end 

Он сопоставляется с маршрутом с именем auth_user, как показано здесь в моем файле rout.rb:

Rails.application.routes.draw do

  resources :reviews

  resources :people do 
    resources :reviews 
  end 

  post 'auth_user' => 'authentication#authenticate_user'

  devise_for :users, :controllers => {sessions: 'sessions', registrations: 
'registrations'}
  # For details on the DSL available within this file, see 
http://guides.rubyonrails.org/routing.html
end

Все мои другие маршруты работают, включая отправку сообщений на разработанные маршруты, но этот дает 500 внутреннюю ошибку сервера. Любые идеи о том, что может быть причиной такого поведения, с благодарностью! Для чего это стоит, я на Rails 5.1.5, JWT 2.1.0 и Devise 4.4.3. Спасибо!

Я проверил логи героки после попытки отправить запрос. Они выглядят так:

2018-04-26T20:53:32.801349+00:00 app[web.1]: I, [2018-04-26T20:53:32.801222 #4]  INFO -- : [bb58b729-4d79-4940-b73d-2bc433c8d224] Started POST "/auth_user" for 199.116.73.196 at 2018-04-26 20:53:32 +0000
2018-04-26T20:53:32.824053+00:00 app[web.1]: I, [2018-04-26T20:53:32.823923 #4]  INFO -- : [bb58b729-4d79-4940-b73d-2bc433c8d224] Processing by AuthenticationController#authenticate_user as */*
2018-04-26T20:53:32.824188+00:00 app[web.1]: I, [2018-04-26T20:53:32.824119 #4]  INFO -- : [bb58b729-4d79-4940-b73d-2bc433c8d224]   Parameters: {"email"=>"\"mike@mike.com\"", "password"=>"[FILTERED]"}
2018-04-26T20:53:32.953483+00:00 app[web.1]: D, [2018-04-26T20:53:32.953329 #4] DEBUG -- : [bb58b729-4d79-4940-b73d-2bc433c8d224]   [1m[36mUser Load (8.4ms)[0m  [1m[34mSELECT  "users".* FROM "users" WHERE "users"."email" = $1 ORDER BY "users"."id" ASC LIMIT $2[0m  [["email", "\"mike@mike.com\""], ["LIMIT", 1]]
2018-04-26T20:53:32.963709+00:00 app[web.1]: I, [2018-04-26T20:53:32.963569 #4]  INFO -- : [bb58b729-4d79-4940-b73d-2bc433c8d224] Completed 500 Internal Server Error in 139ms (ActiveRecord: 53.2ms)
2018-04-26T20:53:32.964567+00:00 app[web.1]: F, [2018-04-26T20:53:32.964492 #4] FATAL -- : [bb58b729-4d79-4940-b73d-2bc433c8d224]   
2018-04-26T20:53:32.964715+00:00 app[web.1]: F, [2018-04-26T20:53:32.964649 #4] FATAL -- : [bb58b729-4d79-4940-b73d-2bc433c8d224] NoMethodError (undefined method `valid_password?' for nil:NilClass):
2018-04-26T20:53:32.964805+00:00 app[web.1]: F, [2018-04-26T20:53:32.964742 #4] FATAL -- : [bb58b729-4d79-4940-b73d-2bc433c8d224]   
2018-04-26T20:53:32.964904+00:00 app[web.1]: F, [2018-04-26T20:53:32.964844 #4] FATAL -- : [bb58b729-4d79-4940-b73d-2bc433c8d224] app/controllers/authentication_controller.rb:4:in `authenticate_user'
2018-04-26T20:53:32.966716+00:00 heroku[router]: at=info method=POST path="/auth_user" host=rateyouracquaintanceapi.herokuapp.com request_id=bb58b729-4d79-4940-b73d-2bc433c8d224 fwd="199.116.73.196" dyno=web.1 connect=1ms service=172ms status=500 bytes=203 protocol=https 

Все еще немного сбит с толку относительно того, что ломается, но по крайней мере теперь ясно, где проблема!

Измените код в authenticate_user на это:

def authenticate_user
    user = User.find_for_database_authentication(email: params[:email])
    if user && user.valid_password?(params[:password])
      render json: payload(user) 
    else
      render json: {errors: ['Invalid Username/Password']}, status: 
:unauthorized
    end
  end 

Теперь я получаю ожидаемый ответ json, если пользователь не был найден, но если я введу данные для действительного пользователя, он не даст правильного ответа. Может ли это быть проблемой с методом find_for_database_authentication? Журналы теперь показывают это:

2018-04-26T21:24:07.327940+00:00 heroku[router]: at=info method=POST 
path="/auth_user" host=rateyouracquaintanceapi.herokuapp.com 
request_id=95dcfdd7-55d5-4a24-b8e4-d597737c4b02 fwd="199.116.73.196" 
dyno=web.1 connect=1ms service=15ms status=401 bytes=286 protocol=https
2018-04-26T21:24:07.319101+00:00 app[web.1]: I, [2018-04-26T21:24:07.318981 
#4]  INFO -- : [95dcfdd7-55d5-4a24-b8e4-d597737c4b02] Started POST 
"/auth_user" for 199.116.73.196 at 2018-04-26 21:24:07 +0000
2018-04-26T21:24:07.320412+00:00 app[web.1]: I, [2018-04-26T21:24:07.320296 
#4]  INFO -- : [95dcfdd7-55d5-4a24-b8e4-d597737c4b02] Processing by 
AuthenticationController#authenticate_user as */*
2018-04-26T21:24:07.320476+00:00 app[web.1]: I, [2018-04-26T21:24:07.320410 
#4]  INFO -- : [95dcfdd7-55d5-4a24-b8e4-d597737c4b02]   Parameters: 
{"email"=>"\"mike@mike.com\"", "password"=>"[FILTERED]"}
2018-04-26T21:24:07.329226+00:00 app[web.1]: D, [2018-04-26T21:24:07.328689 
#4] DEBUG -- : [95dcfdd7-55d5-4a24-b8e4-d597737c4b02]   [1m[36mUser Load 
(5.1ms)[0m  [1m[34mSELECT  "users".* FROM "users" WHERE "users"."email" 
= 
$1 LIMIT $2[0m  [["email", "\"mike@mike.com\""], ["LIMIT", 1]]
2018-04-26T21:24:07.330108+00:00 app[web.1]: I, [2018-04-26T21:24:07.330005 
#4]  INFO -- : [95dcfdd7-55d5-4a24-b8e4-d597737c4b02] 
[active_model_serializers] Rendered ActiveModel::Serializer::Null with Hash 
(0.17ms)
2018-04-26T21:24:07.330482+00:00 app[web.1]: I, [2018-04-26T21:24:07.330370 
#4]  INFO -- : [95dcfdd7-55d5-4a24-b8e4-d597737c4b02] Completed 401 
Unauthorized in 10ms (Views: 1.0ms | ActiveRecord: 5.1ms)

1 Ответ

0 голосов
/ 27 апреля 2018

Глядя на ваши логи, я вижу:

NoMethodError (undefined method `valid_password?' for nil:NilClass):

Это, вероятно, исходит из строки:

user.valid_password?(params[:password])

Это означает, что ваша user переменная nil. Это происходит потому, что user = User.find_for_database_authentication(email: params[:email]) возвращает nil.

Проверьте, существует ли ваш пользователь в базе данных, запустив консоль rails, используя heroku run rails c. Если нет, создайте его, и ваш код должен работать нормально.

...