我在Rails API上有ruby 到目前为止,逻辑是设计密码重置 这是用于查找用户和保留密码的代码块
def update_password_by_token
@user = User.find_by_reset_password_token!(params[:id])
if @user.reset_password_sent_at < 2.hours.ago
render status: 422, json: {}
else
@user.password = params[:password]
@user.password_confirmation = params[:confirm_password]
if @user.save
render status: 200, json: {}
else
render status: 422, json: {}
end
end
end
这是Android向API发送参数
{
"password":"newpassword",
"confirm_password":"newpassword",
"id":"Upn0QHKNy858yMK1J8x1KA"
}
因此,我更深入地研究了令牌并启动了Rails控制台。
@user = User.find_by_reset_password_token!("Upn0QHKNy858yMK1J8x1KA")
User Load (1.5ms) SELECT "users".* FROM "users" WHERE
"users"."deleted_at" IS NULL AND "users"."reset_password_token" = $1
LIMIT $2 [["reset_password_token", "CtW8XFYUdX3d9J7H1rtfUQ"], ["LIMIT",
1]]
=> #<User id: 57, first_name: "abc", last_name: "def", email:
"kalamasher@gmail.com", deleted_at: nil, authentication_token:
"uTWmP41bgihmSW-Thsog", created_at: "2019-01-10 09:56:30", updated_at:
"2019-01-10 10:33:07", is_confirmed: true, firebase_token:
"caQkNMlpp2s:APA91bEr4NKSKsMJ-VCJaXLd8mxadb7...", tenant_id: 6,
is_admin: false, mobile_device: "android", user_level: "partner">
irb(main):006:0> @user.password ="new@password"
=> "new@password"
irb(main):007:0> @user.password_confirmation ="new@password"
=> "new@password"
irb(main):008:0> @user.save
(2.7ms) BEGIN
User Exists (1.6ms) SELECT 1 AS one FROM "users" WHERE "users"."email"
= $1 AND "users"."deleted_at" IS NULL AND ("users"."id" != $2) AND
"users"."tenant_id" = $3 LIMIT $4 [["email", "kalamasher@gmail.com"],
["id", 57], ["tenant_id", 6], ["LIMIT", 1]]
SQL (1.6ms) UPDATE "users" SET "encrypted_password" = $1,
"reset_password_token" = $2, "reset_password_sent_at" = $3, "updated_at"
= $4 WHERE "users"."id" = $5 [["encrypted_password",
"$2a$10$pRhNupGtOiCeCafNsdiVYuqTNYNZqI.xa2oyGmkRIybmDiYOR.f0i"],
["reset_password_token", nil], ["reset_password_sent_at", nil],
["updated_at", "2019-01-10 11:08:46.354276"], ["id", 57]]
(2.4ms) COMMIT
=> true
更新
A NoMethodError occurred in members#update_password_by_token:
undefined method `password_confirmation=' for nil:NilClass
app/controllers/api/v1/members_controller.rb:85:in `update_password_by_token'
-------------------------------
Request:
-------------------------------
* URL : http:#####/api/members/update_password_by_token
* HTTP Method: POST
* IP address : X.X.X.X
* Parameters : {"password"=>"[FILTERED]", "confirm_password"=>"[FILTERED]", "id"=>"CtW8XFYUdX3d9J7H1rtfUQ", "format"=>"json", "controller"=>"api/v1/members", "action"=>"update_password_by_token"}
* Timestamp : 2019-01-10 10:33:55 UTC
* Server : oacsrv01
* Rails root : releases/20180531092251
* Process: 3967
-------------------------------
Session:
-------------------------------
* session id: nil
* data: {}
-------------------------------
Environment:
-------------------------------
* CONTENT_LENGTH : 75
* CONTENT_TYPE : application/x-www-form-urlencoded
* HTTP_ACCEPT : application/json, text/plain, */*
* HTTP_ACCEPT_ENCODING : gzip, deflate
* HTTP_ACCEPT_LANGUAGE : en-US,en;q=0.9,la;q=0.8
* HTTP_CONNECTION : close
* HTTP_DNT : 1
* HTTP_HOST : host
* HTTP_ORIGIN : http:
* HTTP_REFERER : http:
* HTTP_USER_AGENT : Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
* HTTP_VERSION : HTTP/1.0
* HTTP_X_FORWARDED_FOR : X.X.X.X
* ORIGINAL_FULLPATH : /api/members/update_password_by_token
* ORIGINAL_SCRIPT_NAME :
* PATH_INFO : /api/members/update_password_by_token
* QUERY_STRING :
* REMOTE_ADDR : 127.0.0.1
* REQUEST_METHOD : POST
* REQUEST_PATH : /api/members/update_password_by_token
* REQUEST_URI : /api/members/update_password_by_token
* ROUTES_47174199350780_SCRIPT_NAME :
* SCRIPT_NAME :
* SERVER_NAME : server*****
* SERVER_PORT : 80
* SERVER_PROTOCOL : HTTP/1.0
* SERVER_SOFTWARE : Unicorn 5.3.1
* action_controller.instance : #<Api::V1::MembersController:0x0055cf355102c0>
* action_dispatch.backtrace_cleaner : #<Rails::BacktraceCleaner:0x0055cf347bec20>
* action_dispatch.cookies : #<ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullCookieJar:0x0055cf3553aea8>
* action_dispatch.cookies_digest :
* action_dispatch.cookies_serializer : json
* action_dispatch.encrypted_cookie_salt : encrypted cookie
* action_dispatch.encrypted_signed_cookie_salt : signed encrypted cookie
* action_dispatch.http_auth_salt : http authentication
* action_dispatch.key_generator : #<ActiveSupport::CachingKeyGenerator:0x0055cf32a45810>
* action_dispatch.logger : #<ActiveSupport::Logger:0x0055cf32b27e68>
* action_dispatch.parameter_filter : [:password]
* action_dispatch.redirect_filter : []
* action_dispatch.remote_ip : X.X.X.X
* action_dispatch.request.content_type : application/x-www-form-urlencoded
* action_dispatch.request.flash_hash :
* action_dispatch.request.formats : [#<Mime::Type:0x0055cf31200390 @synonyms=["text/x-json", "application/jsonrequest"], @symbol=:json, @string="application/json", @hash=-2441761977289553219>]
* action_dispatch.request.parameters : {"password"=>"[FILTERED]", "confirm_password"=>"[FILTERED]", "id"=>"CtW8XFYUdX3d9J7H1rtfUQ", "format"=>"json", "controller"=>"api/v1/members", "action"=>"update_password_by_token"}
* action_dispatch.request.path_parameters : {:format=>"json", :controller=>"api/v1/members", :action=>"update_password_by_token"}
* action_dispatch.request.query_parameters : {}
* action_dispatch.request.request_parameters : {"password"=>"[FILTERED]", "confirm_password"=>"[FILTERED]", "id"=>"CtW8XFYUdX3d9J7H1rtfUQ"}
* action_dispatch.request.unsigned_session_cookie: {}
* action_dispatch.request_id : efb6377f-4437-46c5-8e13-5cc40b79692f
* action_dispatch.routes : #<ActionDispatch::Routing::RouteSet:0x0055cf32ca2bf8>
* action_dispatch.secret_key_base : 0a1d165e12a2bc249fdd588b275f670198835b689324af3b36e8b9ab4fe246ec80c97c1cb6d3ba495c7d214a06eb3285f25081ce6d307d520a9c0a6bdd892872
* action_dispatch.secret_token :
* action_dispatch.show_detailed_exceptions : false
* action_dispatch.show_exceptions : true
* action_dispatch.signed_cookie_salt : signed cookie
* devise.skip_storage : true
* rack.cors : #<Rack::Cors::Result:0x0055cf35476f08>
* rack.errors : #<File:0x0055cf2f25d538>
* rack.hijack : #<Unicorn::HttpParser:0x0055cf3003b3d0>
* rack.hijack? : true
* rack.input : #<Unicorn::TeeInput:0x0055cf35421b98>
* rack.logger : #<Logger:0x0055cf2fd86810>
* rack.multiprocess : true
* rack.multithread : false
* rack.request.cookie_hash : {}
* rack.request.form_hash : {"password"=>"[FILTERED]", "confirm_password"=>"[FILTERED]", "id"=>"CtW8XFYUdX3d9J7H1rtfUQ"}
* rack.request.form_input : #<Unicorn::TeeInput:0x0055cf35421b98>
* rack.request.form_vars : [FILTERED]
* rack.request.query_hash : {}
* rack.request.query_string :
* rack.run_once : false
* rack.session : #<ActionController::RequestForgeryProtection::ProtectionMethods::NullSession::NullSessionHash:0x0055cf3553af48>
* rack.session.options : {:skip=>true}
* rack.tempfiles : []
* rack.url_scheme : http
* rack.version : [1, 2]
* unicorn.socket : #<Kgio::Socket:0x0055cf35421e90>
* warden : Warden::Proxy:47174220233180 @config={:default_scope=>:user, :scope_defaults=>{}, :default_strategies=>{:user=>[:rememberable, :database_authenticatable]}, :intercept_401=>false, :failure_app=>#<Devise::Delegator:0x0055cf2fedcd18>}
-------------------------------
Backtrace:
-------------------------------
app/controllers/api/v1/members_controller.rb:85:in `update_password_by_token'
F, [2019-01-10T15:33:56.326625 #3967] FATAL -- : [efb6377f-4437-46c5-8e13-5cc40b79692f]
F, [2019-01-10T15:33:56.326751 #3967] FATAL -- : [efb6377f-4437-46c5-8e13-5cc40b79692f] NoMethodError (undefined method `password_confirmation=' for nil:NilClass):
F, [2019-01-10T15:33:56.326796 #3967] FATAL -- : [efb6377f-4437-46c5-8e13-5cc40b79692f]
F, [2019-01-10T15:33:56.327032 #3967] FATAL -- : [efb6377f-4437-46c5-8e13-5cc40b79692f] app/controllers/api/v1/members_controller.rb:85:in `update_password_by_token'
我在部署的代码中做错了什么。 任何人请指教 预先感谢
答案 0 :(得分:1)
检查您的User
模型是否具有password_digest
属性。 password_confirmation
方法要求您的User
模型具有password_digest
属性。
要使用此方法,请在您的User
模型中,按如下所示添加has_secure_password
方法,
class User < ApplicationRecord
has_secure_password
end
如果您的has_secure_password
模型具有password_digest
, User
方法将添加password_digest
属性。
Fyi,以下是ActiveModel中secure_password.rb
的一部分
module ClassMethods
# Adds methods to set and authenticate against a BCrypt password.
# This mechanism requires you to have a +password_digest+ attribute.
#
# The following validations are added automatically:
# * Password must be present on creation
# * Password length should be less than or equal to 72 bytes
# * Confirmation of password (using a +password_confirmation+ attribute)
#
# If password confirmation validation is not needed, simply leave out the
# value for +password_confirmation+ (i.e. don't provide a form field for
# it). When this attribute has a +nil+ value, the validation will not be
# triggered.
答案 1 :(得分:1)
最后花了一天的时间,我对其进行了整理并开始工作。
唯一的解决方法是从该功能中“排除password_confirmation”。 现在,密码update_password_by_token函数的更新代码如下。
def update_password_by_token
@user = User.find_by_reset_password_token!(params[:id])
if @user.present?
if @user.reset_password_sent_at < 2.hours.ago
render status: 422, json: {}
else
@user.password = params[:password]
if @user.save
render status: 200, json: {}
else
render status: 422, json: {}
end
end
end
end
再次感谢所有尝试在上下文中帮助我的人。 我发布了答案,以便将来对您有所帮助。