How to catch Ldap error and redirect to specified

2019-07-23 14:35发布

问题:

I would like to show my login page with error message like "The system cannot log you on at this time. Please try again later" when there is ldap error during the login process.

Currently, I have used the custom_failure.rb approach as described in https://github.com/plataformatec/devise/wiki/How-To:-Redirect-to-a-specific-page-when-the-user-can-not-be-authenticated and it is able to catch error like invalid username / password and I have redirected it to the login page showing the error messages as desired without problem. But this approach cannot catch the ldap errors.

These ldap errors are shown as a very raw html page like the following:

Errno::ETIMEDOUT in Devise::SessionsController#create

A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. - connect(2)

Rails.root: C:/extratxt/2.2.0/source/ruby/messaging Application Trace | Framework Trace | Full Trace

Request

Parameters:

{"utf8"=>"✓",
 "user"=>{"username"=>"administrator",
 "password"=>"[FILTERED]",
 "remember_me"=>"0"},
 "commit"=>"Sign in"}

Show session dump

Show env dump Response

Headers:

None

How can I prevent this and instead show my specified page (e.g. login page with my own error message) ? Any idea ? Thanks

回答1:

One way is to override the create session action, but there are a couple steps required to get it working. First, copy the devise views (if you haven't already done so) with

rails g devise:views

Then you need to create a sessions_controller.rb file that extends Devise::SessionsController:

# /app/controllers/sessions_controller.rb
class SessionsController < Devise::SessionsController

  # copied from [...]/gems/devise-1.4.5/app/controllers/sessions_controller.rb
  # To find the path to your gem, use 'bundle show devise' 
  def create

    begin
      resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#new")
      set_flash_message(:notice, :signed_in) if is_navigational_format?
      sign_in(resource_name, resource)
      respond_with resource, :location => redirect_location(resource_name, resource)
    rescue Net::LDAP::LdapError
      # handle your error
      respond_to do |format|
        format.html { redirect_to new_user_session_path, :notice => $!.to_s }
        format.json { render json: $!.to_s }
      end
    end

  end
end

Finally, in your config/routes.rb, you need to tell devise to use your customized controller:

devise_for :users, :controllers => { :sessions => :sessions }