【问题标题】:Rails - Securely updating user informationRails - 安全更新用户信息
【发布时间】:2014-01-21 00:04:48
【问题描述】:

在许多书籍和教程中,我看到人们在用户控制器中实现 update 方法,通过 params[:id] 或 session[:id] 查找用户数据。但是,我觉得可以简单地修改会话或地址栏来侵入别人的帐户并修改他/她的信息。那么如何确保用户只能更新他/她自己的信息而不是更改其他信息。

【问题讨论】:

标签: ruby-on-rails login


【解决方案1】:

答案是特定于应用程序的。您需要首先“找到”记录 - 如何找到该记录的详细信息取决于应用程序。

是的,正如您所指出的,您不应该只是盲目地实例化记录并更新它。您的业​​务逻辑需要智能地找到相关记录,然后再将其公开以进行更新。

【讨论】:

    【解决方案2】:

    将 User 模型与任何其他模型一样对待,并向其添加您的身份验证,并要求用户在 uddate 方法中登录(例如,某些身份验证方法的 current_user )。

    if current_user
      update_stuff and redirect
    else
      :notice => 'Not authd' and redirect
    end 
    

    【讨论】:

      【解决方案3】:

      我曾经在处理需要将某些内容设为私有的应用程序时遇到过这个问题。我所做的是使用DeviseCancan 以及出色的rails 实践。我使用 Devise 进行身份验证,cancan 进行授权。

      在某些情况下,您可以使用 hidden_​​field 通过表单传递用户 ID。我建议在您的控制器创建操作中传递 user_id,并且在使用设计时您可以访问 current_user 方法,该方法只会根据当前用户会话和 id 创建模型。

      使用 cancan 保护用户信息。例如,如果我只能向用户展示这样的照片,而用户 2 没有看到这些照片。

      @photos = current_user.photos #only grabs current users photos
      

      使用 cancan,我可以通过执行类似操作来阻止用户手动输入 users/2/edit 之类的 url

      能力.rb

      can :manage, Photo, :user_id => user.id
      

      controller.rb

      load_and_authorize_resource :photo
      
      def index
        authorize! :index, @photo
      end
      

      【讨论】:

        【解决方案4】:

        我实际上已经围绕这个主题进行了相当多的应用程序构建/研究,所以我将尝试给出详细的答案。

        以同样的方式,您可以在非用户、登录用户和管理员帐户之间划分应用程序或网站的部分,您可以实施检查以确保,例如,只有正确的用户可以更改他们的帐户密码。以下是您可能用于此类方法的测试:

        describe "as wrong user" do
          let(:user) { FactoryGirl.create(:user) }
          let(:wrong_user) { FactoryGirl.create(:user, email: "wrong@example.com") }
          before { sign_in user, no_capybara: true }
        
          describe "submitting a GET request to the Users#edit action" do
            before { get edit_user_path(wrong_user) }
            specify { expect(response.body).not_to match(full_title('Edit user')) }
            specify { expect(response).to redirect_to(root_url) }
          end
        
          describe "submitting a PATCH request to the Users#update action" do
            before { patch user_path(wrong_user) }
            specify { expect(response).to redirect_to(root_url) }
          end
         end
        end
        

        如果您不熟悉测试(或不确定这具体是做什么的),我会解释:

        在代码中,工厂可以选择一个选项(下面这一行)

        FactoryGirl.create(:user, email: "wrong@example.com")
        

        这基本上创建了一个与默认电子邮件地址不同的用户。然后发生的所有事情就是测试指定错误的用户不应访问原始用户的编辑或更新操作。

        下一步是添加一个前置过滤器来检查当前用户的状态。这可能会出现在您的 users_controller.rb 文件中。

        before_action :correct_user,   only: [:edit, :update]
        

        然后(仍然在 users_controller.tb 文件中)创建一个私有方法来检查当前用户是否有权修改数据,否则会将它们重定向回根 url(如果你喜欢你可以使用 [:notice]说“你无权访问这部分应用程序”或类似的东西)

        private
        def correct_user
          @user = User.find(params[:id])
          redirect_to(root_url) unless current_user?(@user)
        end
        

        correct_user 过滤器使用您在 Sessions 帮助器中定义的 current_user? 布尔方法,如下所示:

        def current_user
        remember_token = User.encrypt(cookies[:remember_token])
        @current_user ||= User.find_by(remember_token: remember_token)
        end
        
        def current_user?(user)
        user == current_user
        end
        

        当涉及到谁可以访问什么时,这并不是安全的全部教条,但我希望它能够为您提供问题中提到的缺失细节。

        【讨论】:

          猜你喜欢
          • 2012-01-20
          • 2017-10-29
          • 1970-01-01
          • 1970-01-01
          • 2020-07-24
          • 2013-08-26
          • 1970-01-01
          • 2011-02-22
          • 2017-01-01
          相关资源
          最近更新 更多