Rails 5和Knock gem:无法验证用户身份

时间:2018-04-23 11:48:28

标签: ruby-on-rails authentication jwt

重现的步骤:

Bundler安装以下Gemfile:

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.3.1'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.0'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# 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', '~> 4.0'
# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
gem 'knock'


# Use ActiveStorage variant
# gem 'mini_magick', '~> 4.8'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.1.0', require: false

# 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', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  gem 'listen', '>= 3.0.5', '< 3.2'
  # 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]

生成用户模型,Knock配置和Knock token_controller

rails g model User
rails g knock:install
rails g knock:token_controller User

用户模型:

class User < ApplicationRecord
    has_secure_password

    def self.from_token_request request
        username = request.params["auth"] && request.params["auth"]["username"]
        self.find_by username: username
    end
end

UserTokenController

class UserTokenController < Knock::AuthTokenController

    skip_before_action :verify_authenticity_token

    private
    def auth_params
        params.require(:auth).permit(:username, :password)
    end
end

在向用户播种数据库之后,我尝试将匹配的凭据发布到Postman。服务器响应错误500和以下日志:

Started POST "/api/user_token" for ::1 at 2018-04-23 13:18:14 +0200
   (0.1ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
  ↳ /var/lib/gems/2.3.0/gems/activerecord-5.2.0/lib/active_record/log_subscriber.rb:98
Processing by UserTokenController#create as */*
  Parameters: {"auth"=>{"username"=>"majje", "password"=>"[FILTERED]"}}
majje
  User Exists (0.1ms)  SELECT  1 AS one FROM "users" WHERE "users"."username" = ? LIMIT ?  [["username", "majje"], ["LIMIT", 1]]
  ↳ app/models/user.rb:7
true
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."username" = ? LIMIT ?  [["username", "majje"], ["LIMIT", 1]]
  ↳ app/models/user.rb:8
Completed 500 Internal Server Error in 86ms (ActiveRecord: 0.8ms)



TypeError (no implicit conversion of nil into String):

jwt (1.5.6) lib/jwt.rb:75:in `digest'
jwt (1.5.6) lib/jwt.rb:75:in `sign_hmac'
jwt (1.5.6) lib/jwt.rb:36:in `sign'
jwt (1.5.6) lib/jwt.rb:96:in `encoded_signature'
jwt (1.5.6) lib/jwt.rb:106:in `encode'
knock (2.1.1) app/model/knock/auth_token.rb:14:in `initialize'
knock (2.1.1) app/controllers/knock/auth_token_controller.rb:22:in `new'
knock (2.1.1) app/controllers/knock/auth_token_controller.rb:22:in `auth_token'
knock (2.1.1) app/controllers/knock/auth_token_controller.rb:8:in `create'
actionpack (5.2.0) lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
actionpack (5.2.0) lib/abstract_controller/base.rb:194:in `process_action'
actionpack (5.2.0) lib/action_controller/metal/rendering.rb:30:in `process_action'
actionpack (5.2.0) lib/abstract_controller/callbacks.rb:42:in `block in process_action'
activesupport (5.2.0) lib/active_support/callbacks.rb:132:in `run_callbacks'
actionpack (5.2.0) lib/abstract_controller/callbacks.rb:41:in `process_action'
actionpack (5.2.0) lib/action_controller/metal/rescue.rb:22:in `process_action'
actionpack (5.2.0) lib/action_controller/metal/instrumentation.rb:34:in `block in process_action'
activesupport (5.2.0) lib/active_support/notifications.rb:168:in `block in instrument'
activesupport (5.2.0) lib/active_support/notifications/instrumenter.rb:23:in `instrument'
activesupport (5.2.0) lib/active_support/notifications.rb:168:in `instrument'
actionpack (5.2.0) lib/action_controller/metal/instrumentation.rb:32:in `process_action'
actionpack (5.2.0) lib/action_controller/metal/params_wrapper.rb:256:in `process_action'
activerecord (5.2.0) lib/active_record/railties/controller_runtime.rb:24:in `process_action'
actionpack (5.2.0) lib/abstract_controller/base.rb:134:in `process'
actionview (5.2.0) lib/action_view/rendering.rb:32:in `process'
actionpack (5.2.0) lib/action_controller/metal.rb:191:in `dispatch'
actionpack (5.2.0) lib/action_controller/metal.rb:252:in `dispatch'
actionpack (5.2.0) lib/action_dispatch/routing/route_set.rb:52:in `dispatch'
actionpack (5.2.0) lib/action_dispatch/routing/route_set.rb:34:in `serve'
actionpack (5.2.0) lib/action_dispatch/journey/router.rb:52:in `block in serve'
actionpack (5.2.0) lib/action_dispatch/journey/router.rb:35:in `each'
actionpack (5.2.0) lib/action_dispatch/journey/router.rb:35:in `serve'
actionpack (5.2.0) lib/action_dispatch/routing/route_set.rb:840:in `call'
rack (2.0.4) lib/rack/etag.rb:25:in `call'
rack (2.0.4) lib/rack/conditional_get.rb:38:in `call'
rack (2.0.4) lib/rack/head.rb:12:in `call'
activerecord (5.2.0) lib/active_record/migration.rb:559:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
activesupport (5.2.0) lib/active_support/callbacks.rb:98:in `run_callbacks'
actionpack (5.2.0) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
railties (5.2.0) lib/rails/rack/logger.rb:38:in `call_app'
railties (5.2.0) lib/rails/rack/logger.rb:26:in `block in call'
activesupport (5.2.0) lib/active_support/tagged_logging.rb:71:in `block in tagged'
activesupport (5.2.0) lib/active_support/tagged_logging.rb:28:in `tagged'
activesupport (5.2.0) lib/active_support/tagged_logging.rb:71:in `tagged'
railties (5.2.0) lib/rails/rack/logger.rb:26:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/request_id.rb:27:in `call'
rack (2.0.4) lib/rack/runtime.rb:22:in `call'
activesupport (5.2.0) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (5.2.0) lib/action_dispatch/middleware/static.rb:127:in `call'
rack (2.0.4) lib/rack/sendfile.rb:111:in `call'
railties (5.2.0) lib/rails/engine.rb:524:in `call'
puma (3.11.4) lib/puma/configuration.rb:225:in `call'
puma (3.11.4) lib/puma/server.rb:632:in `handle_request'
puma (3.11.4) lib/puma/server.rb:446:in `process_client'
puma (3.11.4) lib/puma/server.rb:306:in `block in run'
puma (3.11.4) lib/puma/thread_pool.rb:120:in `block in spawn_thread'

我试图按照其他人发布的几个指南。 我也尝试了文档。 最后,我试图谷歌搜索希望找到有同样问题的人。结果让我觉得有点孤单。任何人都知道问题可能是什么?

3 个答案:

答案 0 :(得分:2)

我相信你的config / initializers / knock.rb

中有一行
  # config.token_secret_signature_key = -> { Rails.application.secrets.secret_key_base }

在rails 5.2中,没有Rails.application.secrets.secret_key_base,这就是为什么异常告诉它需要一个String而不是nil.So你可以像这样取消注释:

config.token_secret_signature_key = -> { "yoursercet" }

您可以阅读此issue

答案 1 :(得分:2)

在使用Rails 5.2(new approach to handle app secrets附带)时,您需要像这样编辑config/initializers/knock.rb

config.token_secret_signature_key = -> { Rails.application.credentials.read }

答案 2 :(得分:0)

取消注释config/initializers/knock.rb中的这一行

# config.token_secret_signature_key = -> { Rails.application.secrets.secret_key_base }

并更新Rails.applications.secrets.secret_key_base

config.token_secret_signature_key =-> {Rails.application.credentials.secret_key_base}

好运(y)