我的数据库中有一个模型,其“show”操作可以在以下URL中查看:
mysite.com/project/12
mysite.com/project/14
我的系统设置方式,有几种定义的方法可以访问它们:
mysite.com/companyname/projectid
,公司可能会将自己传递给想要访问的某些人。请注意,此自定义路由会运行单独的控制器操作,该操作会设置一些内部分析,然后重定向到show
操作。我想限制以mysite.com/project/14
开头的能力,然后只需更改ID,从而查看任何项目。我怎么能这样做?
我对这个问题的目标不仅仅是混淆记录ID,以便更难发现某些记录。相反,我希望只有两种允许访问project/12
的方法:
不应该直接输入project/12
。目前,我认为最好的方法是通过上述两种方法传递project#show
动作获取的代码。我只是不知道如何实现这个,如果有潜在的缺点。
答案 0 :(得分:2)
最简单的方法是将项目与用户或帐户相关联,然后在浏览非公共路径时要求进行身份验证。如果您设置了关联,则可以执行以下操作:
@user = current_user
@project = @user.projects.find(params[:id])
这将确保给定用户只能找到他们拥有的项目。
如果您不想要授权,并且只是想要混淆,那么您将无法在路径中单独使用“id”(因为它是连续的)。您可以将'id'与存储在模型中的随机密钥配对(/ projects / 1?key = 1234),也可以使用GUID而不是id。
答案 1 :(得分:2)
无论你想出什么 - 由于这个简单的要求,它最终会因为默默无闻而变得安全:
用户点击我们提供的链接 他们的主页(我怎么能确保这一点 链接单独到达项目12?)
但是,您可以做的是直接猜测项目的正确URL。
我的想法是为每个项目提供一个独特的“令牌” - 如果您没有以项目的所有者身份登录,那么您必须使用该令牌来访问它。
例如,在您的项目模型中,您可以拥有:
class Project
before_create :set_public_token
protected
def set_public_token
# Randomizes a 20-digit long hex code
self.token = ActiveSupport::SecureRandom.hex(20)
end
end
然后,在你的项目的show动作中你需要有这个:
class ProjectsController < ApplicationController
def show
@project = Project.find(params[:id])
# Obviously you would changed signed_in? to whatever method
# you have that verifies someone is logged in
if !signed_in? || @project.owner_id != current_user.id
raise "Unauthorized Access" if @project.token != params[:token]
end
end
end
然后项目的所有者可以将他们项目的“公共”链接分享给他们想要访问它的人,这看起来像这样:
www.example.com/projects/14?token=3jks83kasdkt84h6cd86
同样,任何人使用该网址都可以访问该项目,我认为您无法远离这一点 - 但这使得这样做更加困难。
这与许多密码重置功能的工作方式相同。有权访问密码重置令牌的人可以在您请求密码后重置密码。但是知道使用什么标记会使你年龄增长(使标记更长,以使暴力更难)。
我个人就是如何处理它,以及我过去如何看待这种事情(photobucket,github上的私人要点等)
答案 2 :(得分:1)
好了,现在再次尝试,我有点理解。
首先在您的公共控制器操作中,您要执行以下操作:
def public_redirect
session[:authorized_for] = params[:id]
redirect_to resource_show_path(params[:id])
end
现在在您的私人控制器中:
def show
@resource = current_user.resources.find params[:id]
if @resource # authorized
respond_with @resource # ok
elsif session[:authorized_for] == params[:id] #redirected from public route
@resource = Resource.find params[:id]
respond_with @resource # ok
else
raise NotAuthorizedException # not ok, do something
end
end
这取决于会话。这当然是可以攻击的,但是要弄清楚公共路线要困难得多。请参阅http://guides.rubyonrails.org/security.html#sessions。
您可以将会话技术重用于其他类似需求(例如,您无法从控制器验证用户的主页链接等。
答案 3 :(得分:0)
我有一个类似要求的项目。现在我首先觉得有必要说这是默默无闻的安全 - 因此根本没有太大的安全性。但是对于一些可以没问题的应用程序。
我的模型上有一个创建回调,它生成一个随机字符串(或数字),用作我的ID - 因此不可能很难猜测另一个资源的路径。