在私有控制器方法中返回redirect_to

前言:我正在使用设计进行身份validation。

我试图阻止未经授权的用户查看,编辑或更新其他用户的信息。 我最关心的是用户将DOM中的表单修改为另一个用户的ID,填写表单,然后单击更新。 我已经专门阅读了下面的内容应该有效,但事实并非如此。 关于SO的post建议将validate_current_user方法移动到公共领域,但这也不起作用。

有什么明显的东西我做错了吗? 或者是否有更好的方法来处理我正在尝试做的事情,无论是使用设计还是其他什么?

我的UsersController看起来像这样:

 class UsersController  [:new, :create, :destroy] before_filter :redirect_guests def index redirect_to current_user unless current_user.try(:admin?) if params[:approved] == "false" @users = User.find_all_by_approved(false) else @users = User.all end end def show @user = User.find(params[:id]) validate_current_user @user end def new @user = User.new end def edit @user = User.find(params[:id]) validate_current_user @user end def create @user = User.new(params[:user]) respond_to do |format| if @user.save format.html { redirect_to @user, :notice => 'User was successfully created.' } else format.html { render :action => "new" } end end end def update @user = User.find(params[:id]) validate_current_user respond_to do |format| if @user.update_attributes(params[:user]) format.html { redirect_to @user, :notice => 'User was successfully updated.' } else format.html { render :action => "edit" } end end end private def redirect_guests redirect_to new_user_session_path if current_user.nil? end def validate_current_user if current_user && current_user != @user && !current_user.try(:admin?) return redirect_to(current_user) end end end 

authenticate_admin! 方法看起来像这样:

  def authenticate_admin! return redirect_to new_user_session_path if current_user.nil? unless current_user.try(:admin?) flash[:error] = "Unauthorized access!" redirect_to root_path end end 

编辑你的意思是“它不起作用?”

为了帮助澄清,当我尝试“破解”其他用户的帐户时,我收到此错误:

在此操作中多次调用渲染和/或重定向。 请注意,您只能调用渲染或重定向,每次操作最多一次。 另请注意,重定向和渲染都不会终止操作的执行,因此如果要在重定向后退出操作,则需要执行类似“redirect_to(…)并返回”的操作。

如果我将方法代码内联在单个控制器操作中,它们就可以正常工作。 但是,我不想那样做,因为它不是DRY。

我还应该说明我已经尝试过:

 def validate_current_user if current_user && current_user != @user && !current_user.try(:admin?) redirect_to(current_user) and return end end 

您正在尝试,并且您希望在每个操作之前授权用户。 我建议你使用像CanCan或declarative_authorization这样的标准gem。

继续这种方法你可能最终重新发明轮子。

如果你决定使用cancan,你所要做的就是在ability.rb文件中添加权限(由rails cancan:install生成)

可以[:read,:write,:destroy],:role =>“admin”

在控制器中只需添加load_and_authorize_resource(cancanfilter)。 它将检查用户是否具有当前操作的权限。 如果用户没有持久性,那么它将抛出403禁止的预期,可以在ApplicationController中捕获并适当地处理。

如果你考虑一下, return私有方法只是退出方法并将控制权传递给控制器​​ – 它不会退出操作。 如果要退出操作,则必须再次返回

例如,你可以这样:

 class PostsController < ApplicationController def show return if redirect_guest_posts(params[:guest], params[:id]) ... end private def redirect_guest_post(author_is_guest, post_id) redirect_to special_guest_post_path(post_id) if author_is_guest end end 

如果params [:guest]存在而不是false,则private方法返回truthy并且#show操作退出。 如果条件失败,则返回nil,并继续操作。

尝试,

 before_filter :redirect_guests, :except => [:new, :create, :destroy] 

应该管用。

这是因为您在authenticate_admin中使用了两次重定向! 和redirect_guests用于new,create和destroy动作。

“在此操作中多次调用渲染和/或重定向。请注意,您只能调用渲染或重定向,每次操作最多一次。”

这就是错误的原因。 在show方法中,如果您既不是此帐户的所有者也不是管理员,则您将面临两个操作: redirect_torender

我的建议是将所有重定向逻辑放入before_filter