【发布时间】:2017-06-18 04:34:20
【问题描述】:
我正在尝试使用 auth0 设置 Rails API 进行身份验证。我已按照Auth0 rails API quickstart 的说明进行操作。
这就是我的用户模型的样子:
class User < ActiveRecord::Base
acts_as_paranoid
has_secure_password
has_many :developed_apps, class_name: "App", foreign_key: "developer_id", dependent: :destroy
has_many :installations, foreign_key: "user_id", dependent: :destroy
has_many :non_installations, foreign_key: "user_id", dependent: :destroy
has_many :installed_apps, through: :installations, class_name: "App", source: :app#, counter_cache: true
has_many :non_installed_apps, through: :non_installations, class_name: "App", source: :app#, counter_cache: true
validates :auth0_id_string, uniqueness: true, presence: true
def self.from_token_payload payload
# Returns a valid user, `nil` or raise
# e.g.
self.find_or_create_by!(auth0_id_string: payload["sub"])
#self.first
#nil
end
end
我在db的用户列中只有id、auth0_id_string和password_digest字段。
我的控制器和路由的命名空间如下:/controllers/api/v1/apps_controller.rb
module Api
module V1
class AppsController < ApplicationController
before_action :authenticate_user
before_action :set_app, only: [:show, :update, :destroy]
before_action :require_developer, only: [:update, :destroy]
ITEMS_PER_PAGE = 2
def index
if params[:page]
@page_no = params[:page].to_i
else
@page_no = 1
end
if !@page_no.to_i.between?(1,((App.count.to_f/ITEMS_PER_PAGE).ceil))
render json: { errors: ["Invalid page number."] }, status: 400 and return
end
@apps = App.offset((@page_no - 1) * ITEMS_PER_PAGE).limit(ITEMS_PER_PAGE)
render json: { :last => (@page_no == (App.count.to_f/ITEMS_PER_PAGE).ceil), :data => @apps }
end
def show
render json: @app
end
def create
@app = App.new(app_params)
@app.developer = current_user
if @app.save
render json: @app
else
render json: { errors: ["Invalid attributes."] }, status: 400
end
end
def update
if @app.update(app_params)
render json: @app
else
render json: { errors: ["Invalid attributes."] }, status: 400
end
end
def destroy
if @app.destroy
render json: { errors: ["Deletion successful."] }, status: 200
else
render json: { errors: ["Deletion failed."] }, status: 500
end
end
private
def set_app
@app = App.find(params[:id])
end
def require_developer
if current_user != @app.developer
render json: { errors: ["Authorized users only."] }, status: :unauthorized
end
end
def app_params
params.require(:app).permit(:name, :description, :blob_location)
end
end
end
end
routes.rb:
Rails.application.routes.draw do
namespace :api, defaults: {format: :json} do
namespace :v1 do
resources :apps
end
end
end
我已将bcrypt 添加到Gemfile 中以获取has_secure_password。application_controller.rb 因为knock gem 自述文件说它是必需的:
/controllers/application_controller.rb:
class ApplicationController < ActionController::API
include Knock::Authenticable
end
我在标题中包含Authorization 为Bearer <jwt_token>,我已验证的令牌在 jwt.io 和其他网站上是正确的。
来自 Postman 的 HTTP sn-p:
GET /api/v1/apps HTTP/1.1
Host: localhost:3000
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6InNpZC5zd2FwbmlsZGV2ZXNoQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpc3MiOiJodHRwczovL3NpZGV2ZXNoLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw1ODkxNDMxZDg1OGQwNDY5YjgwOGFmZmEiLCJhdWQiOiJ1NFhpZUxoRzBJMUZ5YmxGNFFaSWZVN2JkdDhkcm5CZSIsImV4cCI6MTQ4NTk1MjA0NCwiaWF0IjoxNDg1OTE2MDQ0fQ.rRExJkabeB_xrdHpsUIELA9jUSJZq4mxlkDMt6T-OgA
Cache-Control: no-cache
Postman-Token: 4dc93848-3f9d-6366-3a01-c4f6a86a7640
这是我的 Gemfile 版本信息:
source 'https://rubygems.org'
git_source(:github) do |repo_name|
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
"https://github.com/#{repo_name}.git"
end
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.0.1'
# Use postgresql as the database for Active Record
gem 'pg', '~> 0.18'
# Use Puma as the app server
gem 'puma', '~> 3.0'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
# gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 3.0'
# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
gem 'knock', '~> 2.0'
gem "paranoia", "~> 2.2"
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
# gem 'rack-cors'
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platform: :mri
end
group :development do
gem 'listen', '~> 3.0.5'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
每次我发送请求时,我得到的只是标题中提到的响应。
虽然我注意到如果我从标题中删除授权,我会在日志中得到这个:
Started GET "/api/v1/apps" for 127.0.0.1 at 2017-02-01 15:27:38 +0530
Processing by Api::V1::AppsController#index as JSON
User Load (77.1ms) SELECT "users".* FROM "users" WHERE "users"."deleted_at" IS NULL AND "users"."auth0_id_string" IS NULL LIMIT $1 [["LIMIT", 1]]
(0.1ms) BEGIN
User Exists (0.4ms) SELECT 1 AS one FROM "users" WHERE "users"."auth0_id_string" IS NULL AND "users"."deleted_at" IS NULL LIMIT $1 [["LIMIT", 1]]
(0.2ms) ROLLBACK
Filter chain halted as :authenticate_user rendered or redirected
Completed 401 Unauthorized in 299ms (ActiveRecord: 80.8ms)
为什么这不适用于此配置?我错过了什么吗?
我在 auth0 论坛中注意到了类似的问题,但那是关于 ruby-jwt gem 中的一些旧问题,对于我当前版本的 jwt gem 应该已经解决,但我也尝试了该解决方案,结果没有差异。 Link。
【问题讨论】:
标签: ruby-on-rails ruby jwt ruby-on-rails-5 auth0