如何解决这个问题,当我尝试在本地系统上进行身份验证时,它工作正常,但是当上传到 heroku 时,它会返回错误 500?

0 ruby heroku jwt bcrypt-ruby heroku-postgres

我是 Rails 和 React 新手,这可能是一个简单的问题,但我似乎无法弄清楚。

我正在尝试使用 ruby​​ on Rails 和 React 作为客户端来实现简单的 jwt 身份验证。我按照以下建议的步骤进行操作: https://www.pluralsight.com/guides/token-based-authentication-with-ruby-on-rails-5-api

它在我的本地系统上按预期工作,但是当我将应用程序上传到heroku时,它总是返回错误:500。所有其他“发布”和“获取”请求正常工作。仅当我尝试进行身份验证并取回 auth_token 时,才会遇到 500 错误。

这是请求格式帖子:localhost:3001/api/authenticate

与身体:

{
    "email": "evin@xyz.com",
    "password": "evin"
}
Run Code Online (Sandbox Code Playgroud)

我通过使用 get 来验证这些数据在 heroku 上是否可用,效果非常好。

我已经花了两天多的时间来解决这个问题。网上有关此身份验证的信息非常少。有很多关于使用 auth0 的建议。但我在这种形式的身份验证方面找不到太多帮助。

这就是我所拥有的

#Path: /app/controllers/application_controller.rb

class ApplicationController < ActionController::API
  before_action :authenticate_request
  attr_reader :current_user

  private

  def authenticate_request
    @current_user = AuthorizeApiRequest.call(request.headers).result
    render json: { error: 'Not Authorized' }, status: 401 unless @current_user
  end
end


#Path: app/controllers/api/authentication_controller.rb

class Api::AuthenticationController < ApplicationController
 skip_before_action :authenticate_request

 def authenticate
   command = AuthenticateUser.call(params[:email], params[:password])

   if command.success?
     render json: { auth_token: command.result }
   else
     render json: { error: command.errors }, status: :unauthorized
   end
 end
end



#Path: /app/commands/authenticate_user.rb

class AuthenticateUser
  prepend SimpleCommand

  def initialize(email, password)
    @email = email
    @password = password
  end

  def call
    JsonWebToken.encode(user_id: user.id) if user
  end

  private

  attr_accessor :email, :password

  def user
    user = User.find_by_email(email)
    return user if user && user.authenticate(password)

    errors.add :user_authentication, 'invalid credentials'
    nil
  end
end


#Path:  /app/commands/authorize_api_request.rb

class AuthorizeApiRequest
  prepend SimpleCommand

  def initialize(headers = {})
    @headers = headers
  end

  def call
    user
  end

  private

  attr_reader :headers

  def user
    @user ||= User.find(decoded_auth_token[:user_id]) if decoded_auth_token
    @user || errors.add(:token, 'Invalid token') && nil
  end

  def decoded_auth_token
    @decoded_auth_token ||= JsonWebToken.decode(http_auth_header)
  end

  def http_auth_header
    if headers['Authorization'].present?
      return headers['Authorization'].split(' ').last
    else
      errors.add(:token, 'Missing token')
    end
    nil
  end
end




#Path: /lib/json_web_token.rb

class JsonWebToken
 class << self
   def encode(payload, exp = 24.hours.from_now)
     payload[:exp] = exp.to_i
     JWT.encode(payload, Rails.application.secrets.secret_key_base)
   end

   def decode(token)
     body = JWT.decode(token, Rails.application.secrets.secret_key_base)[0]
     HashWithIndifferentAccess.new body
   rescue
     nil
   end
 end
end





#path: /config/application.rb

require_relative 'boot'

require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "action_cable/engine"
# require "sprockets/railtie"
require "rails/test_unit/railtie"

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module Deveycon
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.

    #Autoload lib for encrypt and decrypt
    config.autoload_paths << Rails.root.join('lib')

    # Only loads a smaller set of middleware suitable for API only apps.
    # Middleware like session, flash, cookies can be added back manually.
    # Skip views, helpers and assets when generating a new resource.
    config.api_only = true
  end
end

Run Code Online (Sandbox Code Playgroud)

小智 5

我遇到了类似的问题,上传到 Heroku 后,API 在本地主机上完美运行,即使标头上有令牌,我仍然在安全页面上未经授权。我添加了

production:
   secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
Run Code Online (Sandbox Code Playgroud)

config/secrets.yml