如何在rails中加密和解密ID?

时间:2017-11-09 10:02:50

标签: ruby-on-rails encryption

我要求用户应该登录,并且应该登陆特定页面。

用户基本上会在他的电子邮件中获得一个链接,点击该链接后,用户将登录到系统并登陆特定页面。目前,我正在使用记录ID(用户ID)实现此功能。

网址看起来像这样。

localhost:3000/details?user_id=412

def details
  @user = User.find(user_id)
  signin(@user)
end

由于上述网址,任何人都可以通过更改ID随机访问其他用户帐户。我希望这个id在url中加密,在控制器动作中我想要解密它。我不希望在我想要仅为此操作实现的应用程序中加密。

例如:

localhost:3000/details?user_id=SnrIcaMA8rikrnNX6RRKNw

def details
  @user = User.find(decrypt(user_id))
  signin(@user)
end

3 个答案:

答案 0 :(得分:2)

此处无需加密。

最简单的解决方案是向用户表email_token(或其他)添加一个新字段,并将其设置为您想要的任何随机值。 SecureRandom.hexSecureRandom.uuid就是很好的例子。

然后您只需使用此令牌生成链接,而不是用户ID。您的链接将如下所示:

 example.com/details?token=d3fff15f2e1707719a2acbd4c1edd110

在您的控制器中,您可以执行类似

的操作
user = User.where(email_token: params[:token]).first
if user
  # show page
else
  # redirect to "not authorized" page
end

祝你好好猜测另一个现有的令牌。

此方案优于从用户标识中获取某些值的一个优点是,如果某个链接/标记被发布到论坛或其他内容,您只需更改受损标记,而不会影响其他用户。

答案 1 :(得分:2)

Rails 5引入了has_secure_token,其中has_secure_password旨在通过消除重新发明轮子的需要来提高安全性。这使用了与Sergio Tulentsev的优秀答案完全相同的令牌,但令牌由SecureRandom.base58生成。

# Schema: User(token:string, auth_token:string)
class User < ActiveRecord::Base
  has_secure_token
  has_secure_token :auth_token
end

user = User.new
user.save
user.token # => "pX27zsMN2ViQKta1bGfLmVJE"
user.auth_token # => "77TMHrHJFvFDwodq8w7Ev2m7"
user.regenerate_token # => true
user.regenerate_auth_token # => true

根据您可以使用的令牌验证用户:

@user = User.find_by!(token: params[:token])

如果您使用的是Devise或只使用Warden,您可以创建一个令牌authentication strategy

module Devise
  module Strategies
    class Token < Base
      def valid? 
        params['token']
      end
      def authenticate!
        u = User.find_by(token: params[:token]) 
        if u 
           fail!("Invalid token")
        else
           success!(u) 
        end
      end
    end
  end
end

答案 2 :(得分:0)

你需要的是非常简单的。你使这个声音比它应该更复杂。

您可以通过两种方式实现这一目标。我实际上在我的应用程序中使用了两者。

  1. 的UUID。而不是使用/user/1使用/user/560a56b2-627b-4c28-a685-8d18674060cb。您可以使用SecureRandom.uuid
  2. 生成UUID
  3. 检查所有权。这是我在我的应用程序中使用的实际代码,它使用Devise进行用户身份验证。
  4. user_controller

    before_action :check_ownership
    
    def check_ownership
      redirect_to authenticated_root_path and return unless user == current_user || current_user.try(:admin)
    end
    

    代码非常自我解释。如果ID为1的root_path正在尝试访问current_user,则会重定向到user/2。如果用户是管理员,则允许他查看user/2