Devise redirect back to the original location after sign in or sign up?

前端 未结 8 2247
野趣味
野趣味 2020-12-14 07:42

Here I\'m using Devise Gem for authentication. If someone want to open page without login then it redirect to sign_in page and after signed in it back to the page which user

相关标签:
8条回答
  • 2020-12-14 08:22

    There's no need to define new methods in Devise 4.4.3. Just call method DeviseController#after_sign_in_path_for directly.

    Code like this:

      class YourController < DeviseController
    
        # ... 
        if manager.valid_password? params[:manager][:password]
          sign_in manager
    
          # call this method directly , if your controller extends DeviseController
          redirect_to after_sign_in_path_for(manager), notice: 'welcome!'
        end
    

    Also, if you are using your customized login method and using DeviseController, you must NOT use this code:

    # this method will login automatically, in most cases this method is 
    # useless and misleading.  
    prepend_before_action :allow_params_authentication!, only: :create
    
    0 讨论(0)
  • 2020-12-14 08:24

    Some of the other solutions here may not work if your login form has its own page, as opposed to, e.g., a login form in the header of every page. After logging in, the user needs to go back two pages, not just one.

    Devise has a nice How To on Redirecting back to the current page after sign in, sign out, update, from which the code below comes.

    Storing the original URL in the session is the best option. In addition to solving the above problem of going back two pages, "Many browsers do not send [the request.referer] header. Therefore the only robust cross-browser way to implement this functionality is by using the session."

    When storing URLs in the session, it's important not to store the URL for any POST, PUT, or DELETE request, nor any XHR request, i.e. nothing to which the user can't actually be redirected.

    Note that after signing out, the user's session is destroyed, so the stored URL is gone. In this case, the user can be sent back to request.referer. This seems acceptable since most websites have a sign out link on every page, so returning to the referrer will actually work.

    class ApplicationController < ActionController::Base
      before_action :store_user_location!, if: :storable_location?
      before_action :authenticate_user!
    
      private
        def storable_location?
          request.get? && is_navigational_format? && !devise_controller? && !request.xhr? 
        end
    
        def store_user_location!
          store_location_for(:user, request.fullpath)
        end
    
       def after_sign_in_path_for(resource_or_scope)
         stored_location_for(resource_or_scope) || super
       end
    
       def after_sign_out_path_for(resource_or_scope)
         request.referrer || super
       end
    end
    
    0 讨论(0)
  • 2020-12-14 08:27

    You don't need all this code. Devise (as the latest versions) already saves the location for you.

    Just use this:

    def after_sign_in_path_for(resource)
      request.env['omniauth.origin'] || stored_location_for(resource) || root_url
    end
    

    This will redirect user to the latest omniauth.source, or the stored_location and is last case, the root url.

    I thought I was required to create that method, but Devise already does it.

    Source: https://github.com/plataformatec/devise/wiki/How-To:-redirect-to-a-specific-page-on-successful-sign-in

    0 讨论(0)
  • 2020-12-14 08:27

    As pointed out in the official documentation, the simpler solution would be to simply add this to your application_controller.rb:

    class ApplicationController < ActionController::Base
    
    
    private
    
    # If your model is called User
    def after_sign_in_path_for(resource)
      session["user_return_to"] || root_path
    end
    

    Important Note (Which I also overlooked) is that for this to work you will need to call authenticate_user! method, available by default in Devise, in your controller's before_action:. This will call store_location_for available out of the box in Devise, and the rest is handled by the above code in the application_controller.rb, thus eliminating the need to rewrite code to save requesting url.

    0 讨论(0)
  • 2020-12-14 08:27

    I has the same doubt and found this, try it too

    def after_sign_in_path_for(resource_or_scope)
      session.fetch 'user_return_to', admin_root_path
    end
    
    0 讨论(0)
  • 2020-12-14 08:37

    The best resource to seek is the official repo/wiki/issues, and then SO. The answer you found is out of date.

    Here is the answer: https://github.com/plataformatec/devise/wiki/How-To:-Redirect-back-to-current-page-after-sign-in,-sign-out,-sign-up,-update

    Just add the following in ApplicationController for versions devise > 3.2.1:

        # This example assumes that you have setup devise to authenticate a class named User.
    class ApplicationController < ActionController::Base
      before_action :store_user_location!, if: :storable_location?
      # The callback which stores the current location must be added before you authenticate the user 
      # as `authenticate_user!` (or whatever your resource is) will halt the filter chain and redirect 
      # before the location can be stored.
      before_action :authenticate_user!
    
      private
        # Its important that the location is NOT stored if:
        # - The request method is not GET (non idempotent)
        # - The request is handled by a Devise controller such as Devise::SessionsController as that could cause an 
        #    infinite redirect loop.
        # - The request is an Ajax request as this can lead to very unexpected behaviour.
        def storable_location?
          request.get? && is_navigational_format? && !devise_controller? && !request.xhr? 
        end
    
        def store_user_location!
          # :user is the scope we are authenticating
          store_location_for(:user, request.fullpath)
        end
    end
    

    And then to redirect after signing in, you have to override this method:

    def after_sign_in_path_for(resource_or_scope)
      stored_location_for(resource_or_scope) || super
    end
    
    0 讨论(0)
提交回复
热议问题