【问题标题】:Is there a way to know if a page request came from the same application?有没有办法知道页面请求是否来自同一个应用程序?
【发布时间】:2011-12-14 23:53:35
【问题描述】:

在 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”。在域和所有其他可能的情况之前。

如果我能找出上一页中使用的特定控制器和操作(引用者),那也很好。

【问题讨论】:

  • 注意,所有浏览器都不会发送referer信息
  • 有没有具体的不发送referer的?

标签: ruby-on-rails ruby-on-rails-3 request referrer


【解决方案1】:

我认为你看错了。

如果您环顾网络,找到一个具有搜索功能的网站,然后点击链接,您会看到一个显示搜索内容的参数。

这是一个很好的方法。

通过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 那你为什么不让用户点击他们的后退按钮呢?您是否正在尝试设计您不需要的东西?
  • 我有一点特殊的情况:搜索listing不一般,它允许每个item展开而不请求另一个页面,所以这个方法允许我指定一个ID作为anchor,即将打开该项目并在您返回搜索后将页面滚动到该项目。从用户体验的角度来看,它可能有其缺点和优点,但我认为它可能会有所帮助,至少对某些用户而言。
【解决方案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"}

【讨论】:

    【解决方案3】:

    利用request.referrer 创建一个internal_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?,因为您可能会以独特的方式处理这些情况。这将允许您执行以下操作:

      do_something_unique if external_request?
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-18
      • 2014-10-12
      • 2015-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-01
      相关资源
      最近更新 更多