跳到内容 跳到搜索
命名空间
方法
R
U
包含的模块

常量

ILLEGAL_HEADER_VALUE_REGEX = /[\x00-\x08\x0A-\x1F]/.freeze
 

实例公共方法

redirect_back(fallback_location:, allow_other_host: _allow_other_host, **args)

redirect_back_or_to 的软弃用别名,其中 fallback_location 位置提供为关键字参数,而不是第一个位置参数。

# File actionpack/lib/action_controller/metal/redirecting.rb, line 101
def redirect_back(fallback_location:, allow_other_host: _allow_other_host, **args)
  redirect_back_or_to fallback_location, allow_other_host: allow_other_host, **args
end

redirect_back_or_to(fallback_location, allow_other_host: _allow_other_host, **options)

如果可能,将浏览器重定向到发出请求的页面(引用者),否则重定向到提供的默认回退位置。

引用者信息从请求上的 HTTP Referer(原文如此)标头中提取。这是一个可选标头,其在请求中的存在受浏览器安全设置和用户偏好的影响。如果请求缺少此标头,将使用 fallback_location

redirect_back_or_to({ action: "show", id: 5 })
redirect_back_or_to @post
redirect_back_or_to "http://www.rubyonrails.org"
redirect_back_or_to "/images/screenshot.jpg"
redirect_back_or_to posts_url
redirect_back_or_to proc { edit_post_url(@post) }
redirect_back_or_to '/', allow_other_host: false

选项

  • :allow_other_host - 允许或不允许重定向到与当前主机不同的主机,默认为 true。

可以传递给 redirect_to 的所有其他选项都作为选项接受,并且行为相同。

# File actionpack/lib/action_controller/metal/redirecting.rb, line 127
def redirect_back_or_to(fallback_location, allow_other_host: _allow_other_host, **options)
  if request.referer && (allow_other_host || _url_host_allowed?(request.referer))
    redirect_to request.referer, allow_other_host: allow_other_host, **options
  else
    # The method level `allow_other_host` doesn't apply in the fallback case, omit and let the `redirect_to` handling take over.
    redirect_to fallback_location, **options
  end
end

redirect_to(options = {}, response_options = {})

将浏览器重定向到 options 中指定的 target。此参数可以是以下任何一个:

  • Hash - URL 将通过使用 options 调用 url_for 来生成。

  • Record - URL 将通过使用 options 调用 url_for 来生成,这将引用该记录的命名 URL。

  • protocol://(如 http://)或协议相对引用(如 //)开头的 String - 直接作为重定向 target 传递。

  • 不包含协议的 String - 当前协议和主机将前置到字符串中。

  • Proc - 将在控制器上下文中执行的块。应返回 redirect_to 接受的任何选项。

示例

redirect_to action: "show", id: 5
redirect_to @post
redirect_to "http://www.rubyonrails.org"
redirect_to "/images/screenshot.jpg"
redirect_to posts_url
redirect_to proc { edit_post_url(@post) }

除非使用 :status 选项另行指定,否则重定向将作为 302 Found 头发生

redirect_to post_url(@post), status: :found
redirect_to action: 'atom', status: :moved_permanently
redirect_to post_url(@post), status: 301
redirect_to action: 'atom', status: 302

状态代码可以是标准 HTTP 状态代码(以整数形式),也可以是表示小写、下划线和符号化描述的符号。请注意,状态代码必须是 3xx HTTP 代码,否则不会发生重定向。

如果您正在使用 GET 或 POST 以外的 XHR 请求,并在请求后重定向,那么一些浏览器将使用原始请求方法遵循重定向。这可能会导致不良行为,例如双重 DELETE。要解决此问题,您可以返回 303 See Other 状态代码,该代码将使用 GET 请求遵循。

redirect_to posts_url, status: :see_other
redirect_to action: 'index', status: 303

还可以将 flash 消息分配为重定向的一部分。对于常用的 flash 名称 alertnotice 以及通用 flash bucket,有两个特殊访问器。

redirect_to post_url(@post), alert: "Watch it, mister!"
redirect_to post_url(@post), status: :found, notice: "Pay attention to the road"
redirect_to post_url(@post), status: 301, flash: { updated_post_id: @post.id }
redirect_to({ action: 'atom' }, alert: "Something serious happened")

在我们的控制器中,redirect_to 之后的语句会得到执行,因此 redirect_to 不会停止函数的执行。要在 redirect_to 之后立即终止函数的执行,请使用 return。

redirect_to post_url(@post) and return

开放重定向保护

默认情况下,Rails 会保护您的应用程序免受重定向到外部主机的攻击,即所谓的开放重定向。注意:这是 Rails 7.0 中的新默认值,在升级后,通过取消对 config/initializers/new_framework_defaults_7_0.rbraise_on_open_redirects 行的注释来选择加入

在这里,redirect_to 会自动验证潜在不安全的 URL

redirect_to params[:redirect_url]

在不安全重定向的情况下引发 UnsafeRedirectError

要允许任何外部重定向,请传递 allow_other_host: true,尽管在这种情况下使用用户提供的参数是不安全的。

redirect_to "https://rubyonrails.net.cn", allow_other_host: true

有关内部和安全 URL 是什么,或者如何在不安全的情况下回退到备用重定向 URL 的详细信息,请参阅 url_from

# File actionpack/lib/action_controller/metal/redirecting.rb, line 84
def redirect_to(options = {}, response_options = {})
  raise ActionControllerError.new("Cannot redirect to nil!") unless options
  raise AbstractController::DoubleRenderError if response_body

  allow_other_host = response_options.delete(:allow_other_host) { _allow_other_host }

  self.status = _extract_redirect_to_status(options, response_options)

  redirect_to_location = _compute_redirect_to_location(request, options)
  _ensure_url_is_http_header_safe(redirect_to_location)

  self.location      = _enforce_open_redirect_protection(redirect_to_location, allow_other_host: allow_other_host)
  self.response_body = ""
end

url_from(location)

验证传递的 location 是可以安全重定向到的内部 URL 并返回它,如果不是,则返回 nil。可用于包装由参数提供的重定向 URL,并回退到要重定向到的备用 URL

redirect_to url_from(params[:redirect_url]) || root_url

如果 locationrequest.host 在同一主机上,则认为它是内部的和安全的

# If request.host is example.com:
url_from("https://example.com/profile") # => "https://example.com/profile"
url_from("http://example.com/profile")  # => "http://example.com/profile"
url_from("http://evil.com/profile")     # => nil

子域被认为是主机的一部分

# If request.host is on https://example.com or https://app.example.com, you'd get:
url_from("https://dev.example.com/profile") # => nil

注意:与 url_for 类似,它从应用程序内的各种选项生成内部 URL,例如 url_for(@post)。但是,url_from 旨在采用外部参数进行验证,如 url_from(params[:redirect_url])

# File actionpack/lib/action_controller/metal/redirecting.rb, line 175
def url_from(location)
  location = location.presence
  location if location && _url_host_allowed?(location)
end