【问题标题】:Accessing User Password: Variable Scope in Rails访问用户密码:Rails 中的变量范围
【发布时间】:2010-10-18 10:45:45
【问题描述】:

我正在为 Rails 应用程序编写一个非常简单的邮件系统。我正在使用 RESTful 身份验证。 这是一个相当传统的设置,当用户注册和忘记密码时,我会发送相同的电子邮件。 我只是遇到了一个我似乎无法解决的问题。

我想对这两个实例使用相同的电子邮件模板,即使“新用户”电子邮件将来自用户控制器,而“忘记密码”电子邮件将来自密码控制器。

电子邮件看起来像这样:

<%=h @user.name %>, 
Your membership details:
Username: <%=h @user.login %>
Password: <%=h @user.password %>

当用户注册时,这工作得很好,导致一封看起来像这样的电子邮件:

  Bryan,
  Your membership details:
  Username: bryan
  Password: password

不幸的是,当尝试使用此模板从密码控制器发送“忘记密码”电子邮件时,一切都会中断。 不过,令我困惑的是,它只是中断:

  Bryan,
  Your membership details:
  Username: bryan
  Password: 

换句话说,@user.name 仍然有效,@user.login 也是如此。但是由于某种原因,在这种状态下@user.password 没有通过。

感谢您的回复。需要明确的是,在这种情况下,安全性确实不是问题,因此,能够以纯文本形式发送忘记的密码而不是通过重置密码过程会更好,但我很感激这一点通常情况并非如此。

【问题讨论】:

  • 如果安全不是问题,不要要求用户提供密码。如果这是一个问题,请尊重它。说“安全不是问题,但我们会要求用户提供密码(而不是保护它),因为他们很清楚他们中的许多人会提供他们在其他地方使用的密码”是​​不负责任的。
  • 同意 MarkusQ。如果您以明文形式存储密码并且有人能够查看您的用户表,那么该人就可以访问您用户 80% 的电子邮件帐户。

标签: ruby-on-rails ruby variables scope restful-authentication


【解决方案1】:

我猜密码是以散列形式存储的,故意让您无法知道用户的密码。当用户忘记密码时,您需要做的是向用户发送一个链接,该链接仅在几天内有效,让用户在不知道旧密码的情况下重置密码。

【讨论】:

    【解决方案2】:

    如果没有看到您的一些代码,特别是控制器方法,很难说。

    注册电子邮件可能在加密之前使用了密码。未加密的密码通常不可用于以后的操作,因为它已加密存储在 db 中。

    但是,如果您的密码控制器正在设置新密码,而不是尝试检索旧密码,那么问题很可能出在其他地方。

    不管怎样,这就是不看代码就可以做的尽可能多的猜测。

    【讨论】:

      【解决方案3】:

      如果您查看数据库,您将看到密码哈希和盐哈希。

      在将明文密码存储到数据库之前,您必须将明文密码存储在另一个变量中,使用带有明文密码的单独变量,您可以将其传递给 ActiveMailer 并在没有加密的情况下在电子邮件中发送。

      @user = User.find(params[:id])
      password = params[:user][:password]
      options = {
          :password => password,
          :user => @user
      }
      
      if @user.update_attributes(params[:user]) and Mailer.deliver_reset(options)
          flash[:notice] = "Check your email (#{@user.email}) for your new password."
          redirect_to_back_or_default('/')
      else
          flash[:error] = "Look at the errors below"
      end
      

      【讨论】:

        【解决方案4】:

        我同意莎拉·梅的观点。这是由于restful auth存储密码的方式。一般attr_accessor :password在用户模型中为密码设置一个虚拟属性,然后你去注册时使用。在注册阶段,用户对象会将密码属性设置为某个值,但是当您稍后去检索用户记录时,密码字段将为空白。

        无论如何,我认为这不是“最好”的做事方式,向他们发送一个链接,他们可以在其中重置密码,而不仅仅是原始密码,因为如果他们忘记了一次,是什么阻止他们再次忘记密码?

        【讨论】:

        • 是的。这个 attr_accessor :password 过去让我很困惑。我敢打赌这就是问题所在。
        【解决方案5】:

        不要这样做

        许多用户在多个地方使用相同的密码(是的,不应该,但他们确实这样做了)。以纯文本形式存储他们的密码不仅会危及您网站的安全,还会危及您在其他网站上的用户的安全。甚至不要让我开始通过电子邮件以明文形式发送密码。

        按照其他人的建议,使用密码重置系统,而不是“这是您的密码”系统。

        【讨论】:

        • +1 因为明文密码或使用可逆的“哈希”是最大的安全漏洞之一。期间。
        • 安全确实不是这个应用程序的问题,但我通常会同意。
        • @Brian Woods -- 如果安全不是问题,请不要要求用户提供密码。如果这是一个问题,请尊重它。说“安全不是问题,但我们会要求用户提供密码,因为他们很清楚他们中的许多人会提供他们在其他地方使用过的密码”,这是不负责任的。
        • @MarkusQ 那是短视的。如果它是我和几个朋友在内部和非正式使用的应用程序怎么办?在这种情况下,会话存储和密码更多的是关于礼仪而不是安全,构建“重置密码”系统似乎有点过头了。
        • @Brian Woods -- 你对“短视”的定义很奇怪;通常,该术语用于您正在使用的那种推理(假设由于某些东西的范围有限,现在它总是会如此)。它也没有解决真正的问题。你想获取你朋友的密码吗?
        【解决方案6】:

        restful-authentication stores the password only temporarily - 足够长的时间来加密它并保存加密版本。正如其他人提到的那样,这是为了安全。

        由于您不太担心此应用的安全性,我建议为每个用户生成一个唯一令牌,并为他们提供一个用于登录的 URL。因为“密码”(甚至是生成的)而推荐一个 URL 可能会让用户期望他们可以更改它。您可以向您的用户发送电子邮件,例如:

         Bryan,
          Your membership details:
          Username: bryan
          Your url: http://domain.com/x7sjs0qn
        

        您的用户可以点击该 URL 并自动登录。这样一来,您就永远不会让用户有机会向您提供他们可能在其他地方使用的密码,而且 - 如果他们忘记了密码,您可以以纯文本的形式通过电子邮件发送,而不会使他们的其他帐户面临任何风险。

        【讨论】:

          猜你喜欢
          • 2015-06-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-08-16
          • 2010-11-16
          • 2012-06-09
          相关资源
          最近更新 更多