问题
I have my rails application and I am running into a major issue with devise. I have a controller:
class Users::SessionsController < Devise::SessionsController
prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
include Devise::Controllers::InternalHelpers
def new
clean_up_passwords(build_resource)
respond_to do |format|
format.html { render :layout => "sessions" }
format.mobile
end
end
# POST /resource/sign_in
def create
resource = User.find_by_email(params[:user][:email])
resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new")
set_flash_message :notice, :signed_in
sign_in_and_redirect(resource_name, resource)
end
end
The problem is it never logs the user in, it always stops at this line
resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new")
I even put tons of loggers in the actual gem files to see if I could see anything off but nothing and I really have no idea how to fix this. If I comment this line out then the user gets logged in but fails if the email is not in the db and works for any password (which is definitely not the right solution)
How do I fix this?
UPDATE
this works but seems very hackish
# POST /resource/sign_in
def create
resource = User.find_by_email(params[:user][:email])
redirect_to(new_user_session_path, :notice => 'Invalid Email Address or Password. Password is case sensitive.') and return if resource.encrypted_password.blank?
bcrypt = BCrypt::Password.new(resource.encrypted_password)
password = BCrypt::Engine.hash_secret("#{params[:user][:password]}#{resource.class.pepper}", bcrypt.salt)
valid = Devise.secure_compare(password, resource.encrypted_password)
# resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new")
if valid
set_flash_message :notice, :signed_in
sign_in_and_redirect(resource_name, resource)
else
redirect_to(new_user_session_path, :notice => 'Invalid Email Address or Password. Password is case sensitive.') and return
end
end
回答1:
If you want to sign in a user, use the sign_in helper inside your controller's action:
sign_in(:user, user)
回答2:
resource = warden.authenticate!(:scope => resource_name)
sign_in(resource_name, resource)
回答3:
I found this post useful for setting up a login for request specs. https://makandracards.com/makandra/37161-rspec-devise-how-to-sign-in-users-in-request-specs
module DeviseRequestSpecHelpers
include Warden::Test::Helpers
def sign_in(resource_or_scope, resource = nil)
resource ||= resource_or_scope
scope = Devise::Mapping.find_scope!(resource_or_scope)
login_as(resource, scope: scope)
end
def sign_out(resource_or_scope)
scope = Devise::Mapping.find_scope!(resource_or_scope)
logout(scope)
end
end
Include it in your spec_helper
RSpec.configure do |config|
config.include DeviseRequestSpecHelpers, type: :request
end
And sign in as needed
sign_in create(:user, name: 'John Doe')
回答4:
Here is how standard create actions works:
# POST /resource/sign_in
def create
self.resource = warden.authenticate!(auth_options)
set_flash_message!(:notice, :signed_in)
sign_in(resource_name, resource)
yield resource if block_given?
respond_with resource, location: after_sign_in_path_for(resource)
end
https://github.com/plataformatec/devise/blob/master/app/controllers/devise/sessions_controller.rb#L18
来源:https://stackoverflow.com/questions/9342832/how-do-i-login-a-user-with-devise