有没有一种方法可以知道页面请求是否来自同一个应用程序?

7
在Rails3中,有没有一种方法可以检查我现在渲染的页面是否是从同一个应用程序请求的,而不使用硬编码的域名?
我目前的代码如下:
def back_link(car_id = '')
  # Check if search exists
  uri_obj = URI.parse(controller.request.env["HTTP_REFERER"]) if controller.request.env["HTTP_REFERER"].present?
  if uri_obj.present? && ["my_domain.com", "localhost"].include?(uri_obj.host) && uri_obj.query.present? && uri_obj.query.include?('search')
    link_to '◀ '.html_safe + t('back_to_search'), url_for(:back) + (car_id.present? ? '#' + car_id.to_s : ''), :class => 'button grey back'
  end
end

但是这种方法没有检查域名前面的“www。”和其他所有可能的情况。

如果我能找到在先前页面中使用的特定控制器和操作(即引用页),那将会很好。


1
注意,不是所有的浏览器都会发送引用者信息。 - apneadiving
有没有不发送 Referer 的特定程序? - Cristian
3个回答

14

我认为你的看法有些错误。

如果你在网上找到一个具有搜索功能的网站,并点击链接,你将会看到一个参数显示了搜索内容。

这是一个好方法。

通过HTTP_REFERER来实现似乎有点不够可靠,并且不能从书签或者发布的链接中使用。

例如:

/cars/12?from_search=sports+cars

如果你只是想查找params[:from_search],那么你可以直接查找它。

如果你确实需要通过HTTP_REFERER来实现,那么你可能不必担心子域。只需:

def http_referer_uri
  request.env["HTTP_REFERER"] && URI.parse(request.env["HTTP_REFERER"])
end

def refered_from_our_site?
  if uri = http_referer_uri
    uri.host == request.host
  end
end

def refered_from_a_search?
  if refered_from_our_site?
    http_referer_uri.try(:query)['search']
  end
end

谢谢!代码真的很干净!特别喜欢使用 &&(但不知道如果第一个条件不满足它会返回 nil 还是 false?)。使用 params 更加健壮,所以我想我会选择那个。 - Cristian
重点是,我不希望它从书签或发布的链接中工作,因为它的目的是制作一个按钮,以返回到搜索(如果先前进行了搜索)。如果没有,则不显示该按钮。 - Cristian
@Cristian 为什么不让用户点击他们的返回按钮呢?你试图制造一些你不需要的东西吗? - Matthew Rudy
我有一个有点特殊的情况:搜索列表不是普通的,它允许每个项目在不请求另一页的情况下展开,因此这种方法允许我指定一个ID作为锚点,一旦您返回到搜索,它将打开该项并滚动页面到该项。从用户体验的角度来看,它可能有其优点和缺点,但我认为它可能对至少一些用户有所帮助。 - Cristian

2

可以尝试以下方法:

ref = URI.parse(controller.request.env["HTTP_REFERER"])

if ref.host == ENV["HOSTNAME"]
  # do something

尝试从引用页面获取控制器/操作:

ActionController::Routing::Routes.recognize_path(url.path)
  #=> {:controller => "foo", :action => "bar"}

0

创建一个使用request.referrerinternal_request?方法。

request.referrerhostport与您的应用程序的hostport进行比较。

require 'uri' # Might be necesseary.

def internal_request?
  return false if request.referrer.blank?

  referrer = URI.parse( request.referrer )

  application_host = Rails.application.config.action_mailer.default_url_options[ :host ]
  application_port = Rails.application.config.action_mailer.default_url_options[ :port ]

  return true if referrer.host == application_host && referrer.port == application_port

  false
end

然后在需要的地方调用它,最有可能是在application_controller.rb中:

if internal_request?
  do_something
end

一些注意事项:

  • 如果您使用子域名,则可能需要进行修改。不过很容易。
  • 这将需要您在配置中设置ActionMailer的主机和端口,这是常见的操作。
  • 您可能希望将其反向,例如 external_request?,因为您可能需要独特地处理这些情况。这将允许您执行以下操作:

    如果是外部请求,则执行某些唯一操作
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接