我要求用户应该登录,并且应该登陆特定页面。
用户基本上会在他的电子邮件中获得一个链接,点击该链接后,用户将登录到系统并登陆特定页面。目前,我正在使用记录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
答案 0 :(得分:2)
此处无需加密。
最简单的解决方案是向用户表email_token
(或其他)添加一个新字段,并将其设置为您想要的任何随机值。 SecureRandom.hex
或SecureRandom.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)
你需要的是非常简单的。你使这个声音比它应该更复杂。
您可以通过两种方式实现这一目标。我实际上在我的应用程序中使用了两者。
/user/1
使用/user/560a56b2-627b-4c28-a685-8d18674060cb
。您可以使用SecureRandom.uuid
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