Rails防止更改网址

时间:2019-03-07 01:37:41

标签: ruby-on-rails ruby url

我正在尝试找出一种方法来防止某人更改部分网址。我已经设置了我的网站,以便没有人可以注册或创建帐户,以便任何访问的人都是客人。

例如,我已经在网站的此部分中设置了网址,以从1a中查找/pathfinder/a/quest1/1a/q1sub1/的值,以便显示{{1 }}。

如果有人要将q1sub1的值更改为1a,我想测试网址是否已更改并给出某种错误消息。

不确定在这种情况下要共享的代码摘录,如果您需要更多信息,请告诉我。

我愿意接受任何想法,并感谢任何意见。谢谢!

2 个答案:

答案 0 :(得分:0)

URL是设计使然,无法由您的应用程序控制。但是,如果您想跟踪用户以前的位置,则在所有控制器中您都可以访问request.referrer,它应该告诉您请求来自何处。如果您想限制request.referrer,则可以在控制器中添加一些条件逻辑并重定向用户。因此,在您的控制器操作中,如下所示:

def show # for example
  if request.referrer != "http://example.com/myformpage"
    redirect_to root_path, notice: "Invalid access"
  else 
    # do stuff
  end
end

但是,这仍然是不安全的,因为可以伪造标题(感谢@Holgar Just)。如果您确实需要应用程序中的安全性,则应该阅读documentation,并且如果需要对用户权限进行更精细的控制,可以结帐CanCanCan gem

答案 1 :(得分:0)

一种描述您的方法的方法是,使用包含机密pepper的哈希函数,在将URL发送给客户端之前先对URL进行指纹识别。这个想法是,如果客户端篡改了URL,则指纹将不再匹配,并且由于指纹是通过服务器端机密生成的,因此客户端将无法生成与新URL匹配的新指纹。

这里是一个例子。

用户将访问/foo并传递自定义data参数。应用程序将使用此参数来构建格式为/my/secret/:one/path/:two的自定义URL,并将客户端重定向到该URL。这只是为了简化操作,如果将生成的URL用作页面中的<a href="...">,则可以应用相同的方法。

生成的URL包含一个指纹,并且如果客户端篡改了URL或指纹,或者如果缺少指纹,则应用程序将以403响应。

让我们看一下代码。路线:

Rails.application.routes.draw do
  get :foo, to: 'example#foo'
  get '/my/secret/:one/path/:two', to: 'example#bar', as: 'bar'
end

和控制器:

class ExampleController < ApplicationController
  # GET   /foo?data=xx  foo_path
  #
  def foo
    user_data = request[:data]
    go_to_path = bar_path(one: user_data, two: "foobar")
    go_to_path += "?check=#{url_fingerprint(go_to_path)}"

    redirect_to go_to_path
  end

  # GET   /my/secret/:one/path/:two  bar_path
  #
  def bar
    unless valid_request?
      render plain: "invalid request!", status: 403
      return
    end

    render plain: "this is a good request", status: 200
  end

  private

  SECRET = ENV.fetch("URL_FINGERPRINT_SECRET", "default secret")

  # Calculate the fingerprint of a URL path to detect
  # manual tampering.
  #
  # If you want to restrict this to a single client, add
  # some unique identifier stored in a cookie.
  #
  def url_fingerprint(path)
    Digest::SHA2.hexdigest(path + SECRET)
  end

  def valid_request?
    return false unless params[:check].present?
    params[:check] == url_fingerprint(request.path)
  end
end

以此,客户端将以:

$ curl -i -s http://localhost:3000/foo?data=hello | grep Location
Location: http://localhost:3000/my/secret/hello/path/foobar?check=da343dd84accb4c0f5f7ff1d6e68152ac124ca1a39ce4746623bcb7b9043cab3

然后:

curl -i http://localhost:3000/my/secret/hello/path/foobar?check=da343dd84accb4c0f5f7ff1d6e68152ac124ca1a39ce4746623bcb7b9043cab3
HTTP/1.1 200 OK

this is a good request

但是,如果URL被修改:

curl -i http://localhost:3000/my/secret/IWASCHANGED/path/foobar?check=da343dd84accb4c0f5f7ff1d6e68152ac124ca1a39ce4746623bcb7b9043cab3
HTTP/1.1 403 Forbidden

invalid request!

如果指纹本身被修改或丢失,也会发生同样的情况。