
本教程探讨在sinatra应用中尝试获取完整引用url时遇到的常见问题。它解释了为何`request.referrer`等方法有时仅返回域名而非完整路径,并深入剖析了现代浏览器默认的`strict-origin-when-cross-origin` referrer策略如何影响这一行为,同时提供应对策略和注意事项。
在开发Web应用时,我们经常需要了解用户从哪个页面跳转而来,即获取引用(referrer)URL。在Ruby的Sinatra框架中,开发者通常会尝试使用request.referrer或request.env["HTTP_REFERER"]来获取这一信息。然而,在某些特定场景下,尤其是涉及跨域请求时,这些方法可能无法提供完整的引用URL,而只返回协议和域名部分。本文将深入探讨这一现象背后的原因,并提供相应的理解与应对策略。
假设你有一个Sinatra应用,其某个端点(例如/test)提供JavaScript代码,供其他远程网站通过<script src="...">标签调用。你的目标是在Sinatra应用中获取到调用此JavaScript的远程网站的完整URL(包括路径和查询参数)。
以下是一个简单的Sinatra应用示例,用于测试引用URL的获取:
require 'sinatra'
get %r{/test} do
debug = {
:referrer => request.referrer,
:http_referer => request.env["HTTP_REFERER"],
:path_info => request.path_info,
:query_string => request.query_string,
:host => request.host,
:url => request.url,
:path => request.path
}
STDERR.puts debug.inspect
erb "test" # 假设存在一个名为test的erb模板
end如果此Sinatra应用部署在 http://www.server.com,并且一个远程网站 http://www.remote.com/url-with-test-code.html 包含以下HTML代码:
<html> <body> <script src="http://www.server.com/test"></script> </body> </html>
当 http://www.remote.com/url-with-test-code.html 页面加载并请求 http://www.server.com/test 时,我们期望在Sinatra应用中获取到 https://www.remote.com/url-with-test-code.html 作为引用URL。然而,实际观察到的输出可能如下:
{:referrer=>"https://www.remote.com/", :http_referer=>"https://www.remote.com/", :path_info=>"/test", :query_string=>"", :host=>"www.server.com", :url=>"https://www.server.com/test", :path=>"/test"}从输出中可以看出,:referrer 和 :http_referer 键的值都被截断为 https://www.remote.com/,仅包含了协议和域名,而丢失了 /url-with-test-code.html 这一路径信息。
这种引用URL被截断的行为并非Sinatra或Ruby的缺陷,而是现代浏览器默认的Referrer策略所致。
Referrer-Policy HTTP头部 允许网站控制在发起请求时,浏览器应该在 Referer (注意拼写,HTTP头部是单'r') 头部中发送多少引用信息。常见的策略包括:
strict-origin-when-cross-origin 策略的影响:
当一个网站(例如 www.remote.com)请求另一个不同源的资源(例如 www.server.com 上的JavaScript文件)时,如果浏览器采用 strict-origin-when-cross-origin 作为默认Referrer策略,那么在发送给 www.server.com 的请求中,Referer 头部将只包含 www.remote.com 的协议、域名和端口,而不会包含其完整的路径信息。这正是我们观察到的引用URL被截断的原因。
这种策略的演变主要是出于用户隐私和安全考虑。暴露完整的引用URL可能会泄露用户浏览历史或敏感信息。
由于浏览器Referrer策略的限制,直接通过request.referrer在服务器端可靠地获取跨域请求的完整引用URL通常是不可行的。如果你的应用确实需要完整的引用URL,可以考虑以下几种替代方案:
客户端主动传递完整URL: 如果远程网站(www.remote.com)是你所控制的,并且它需要将完整的自身URL传递给你的Sinatra应用,可以通过JavaScript在客户端获取当前页面的完整URL,并将其作为查询参数传递给你的Sinatra端点。
例如,远程网站的HTML可以这样修改:
<html>
<body>
<script>
const fullRemoteUrl = encodeURIComponent(window.location.href);
const scriptElement = document.createElement('script');
scriptElement.src = `http://www.server.com/test?remote_url=${fullRemoteUrl}`;
document.body.appendChild(scriptElement);
</script>
</body>
</html>在Sinatra应用中,你可以通过 request.params['remote_url'] 来获取这个值。
require 'sinatra'
get %r{/test} do
remote_url_from_param = request.params['remote_url']
debug = {
:referrer => request.referrer,
:http_referer => request.env["HTTP_REFERER"],
:remote_url_param => remote_url_from_param # 新增
}
STDERR.puts debug.inspect
erb "test"
end注意事项: 这种方法依赖于远程网站的配合,并且传递的URL可能会受到URL长度限制。同时,客户端传递的数据应被视为不可信,需要进行适当的验证和清理。
重新评估对完整URL的需求: 在许多情况下,仅仅知道请求的来源域名(Origin)可能就已足够满足业务需求,例如用于统计、权限验证(基于域名白名单)等。如果仅需要来源域名,那么request.referrer提供的截断信息已经足够。
控制Referrer-Policy头部(仅限控制引用方): 如果你同时控制引用网站(www.remote.com),并且非常清楚风险,你可以尝试在该网站的响应中设置一个更宽松的 Referrer-Policy HTTP头部,例如 Referrer-Policy: unsafe-url 或 Referrer-Policy: origin-when-cross-origin。 强烈不推荐 unsafe-url,因为它会暴露所有URL,带来安全和隐私风险。即使设置了更宽松的策略,也无法保证所有用户浏览器都会遵守,因为用户或浏览器扩展可能会覆盖此策略。
在Sinatra应用中获取完整引用URL时遇到截断问题,其根本原因在于现代浏览器为了保护用户隐私和安全,默认采用了如 strict-origin-when-cross-origin 这样的Referrer策略。这些策略限制了跨域请求时 Referer 头部所包含的信息量,通常只发送源(协议、域名和端口)。
这意味着,在大多数跨域场景下,服务器端无法直接通过 request.referrer 获取到完整的引用路径。开发者应意识到这一限制,并根据实际需求,考虑通过客户端主动传递信息或重新评估对完整URL的依赖。在设计系统时,务必将浏览器安全策略纳入考量,以确保应用的健壮性和用户隐私。
以上就是Sinatra应用中获取完整引用URL的挑战与浏览器Referrer策略解析的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号