Redirect loop with Devise after_sign_in_path_for

匿名 (未验证) 提交于 2019-12-03 01:32:01

问题:

I'm having a bit of a noob issue. I wanted to get devise to redirect to the last page the user visited. So I did the following...

def after_sign_in_path_for(resource)     request.referer end 

Works great...except if the user is actually logging in through the original form which causes a redirect loop.

I tried

def after_sign_in_path_for(resource)    if (request.referer == "/users/sign_in")   :pages_home  else   request.referer  end  end 

But thats not working, most likely because I have no idea what request.referer is actually returning when it encounters the original user login page (www.example.com/users/sign_in).

Any ideas?

tldr; Using devise, I want to redirect to the page logged in from (i.e /blog/4) unless the page is /users/sign_in

SOLVED:

Matchu was right. The request.referer was returning the domain as well...

http://example.com/users/sign_in 

(note: no www prefix)

I'm still interested in an alternative to request.referer if its an insecure or inefficient way.

回答1:

Don't redirect to referrers - it's generally a bad idea.

Instead, pass a next value across in the query-string or form-data. Perhaps use something like:

def after_sign_in_path_for(resource)   params[:next] || super end 

When a user tries to visit a page requiring authentication (e.g., /admin/posts/3/edit) the authentication before_filter issues a redirect_to new_session_url(:next => request.path). Then code up the login action and view to preserve the :next query-string parameter.



回答2:

How about this:

def after_sign_in_path_for(resource)   sign_in_url = url_for(:action => 'sign_in', :controller => 'users', :only_path => false, :protocol => 'http')     if (request.referer == sign_in_url)     super   else     request.referer   end end 


回答3:

I took Justice's answer and changed it to use sessions instead.

As far as I can see, sessions are simpler then adding the url as param, but they might behave unexpected when a user is browsing a site in multiple tabs, for example. Using sessions is less RESTfull, but simpler and cleaner.

When using CanCan, setting the redirect-path can be done in a central place: the place that handles the "access denied" exceptions:

  rescue_from CanCan::AccessDenied do |exception|     if current_user.nil?       session[:next] = request.fullpath       puts session[:next]       redirect_to new_user_session_path, :alert => exception.message     else       render :file => "#{Rails.root}/public/403.html", :status => 403     end   end 

But you can set this anywhere, actually:

 def edit    if current_user.roles[:moderator].nil?      session[:next] = "/contact"      redirect_to new_user_session_path, :alert => "please contact the moderator for access"    end    # ...  end 

Then, in ApplicationController, you can re-use that session value. Make sure to remove it too, though.

  def after_sign_in_path_for(resource)     path = ''     if session[:next]       path = session[:next]       session[:next] = nil     else       path = super     end      path   end 


回答4:

Here is my code to rescue_from CanCan.

rescue_from CanCan::AccessDenied do |exception|   if current_user.nil?     session[:next] = request.fullpath     puts session[:next]     redirect_to login_url, :alert => "You have  to be logged in to continue"   else     #render :file => "#{Rails.root}/public/403.html", :status => 403     if request.env["HTTP_REFERER"].present?       redirect_to :back, :alert => exception.message     else       redirect_to root_url, :alert => exception.message     end   end end 

What it does: - if the user is not logged in, it redirects to login page - if the user is logged in, but do not have abilities to see the action, it redirects either back or to the root page with alert flash message



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!