Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache mod_重写规则以强制标准百分比编码_Apache_Mod Rewrite_Urlencode_Url Encoding_Percent Encoding - Fatal编程技术网

Apache mod_重写规则以强制标准百分比编码

Apache mod_重写规则以强制标准百分比编码,apache,mod-rewrite,urlencode,url-encoding,percent-encoding,Apache,Mod Rewrite,Urlencode,Url Encoding,Percent Encoding,我们有一个带有动态URL方案的PHP应用程序,该方案要求对字符进行百分比编码,甚至像括号或无括号这样的字符实际上不需要编码。应用程序认为编码“错误”的URL被规范化,然后重定向到“正确”编码 但谷歌和其他用户代理将以不同的方式规范化百分比编码/解码,这意味着当谷歌机器人请求页面时,它将要求提供“错误”的URL,当它返回到“正确”URL的重定向时,谷歌机器人将拒绝遵循重定向并拒绝为页面编制索引 是的,这是我们这边的一个错误。HTTP规范要求服务器以相同的方式处理百分比编码和非百分比编码的无保留字符

我们有一个带有动态URL方案的PHP应用程序,该方案要求对字符进行百分比编码,甚至像括号或无括号这样的字符实际上不需要编码。应用程序认为编码“错误”的URL被规范化,然后重定向到“正确”编码

但谷歌和其他用户代理将以不同的方式规范化百分比编码/解码,这意味着当谷歌机器人请求页面时,它将要求提供“错误”的URL,当它返回到“正确”URL的重定向时,谷歌机器人将拒绝遵循重定向并拒绝为页面编制索引

是的,这是我们这边的一个错误。HTTP规范要求服务器以相同的方式处理百分比编码和非百分比编码的无保留字符。但是现在修复应用程序代码中的问题并不简单,所以我希望通过使用Apache重写规则来避免代码更改,该规则将确保URL从应用程序的角度进行“正确”编码,这意味着,等都是百分比编码,空格编码为
+
,而不是
%20

这里有一个例子,我想重写第一个表单,最后得到第二个表单:

  • www.splunkbase.com/apps/All/4.x/Add-On/app:OPSEC+LEA+for+Check+Point+(Linux)
  • www.splunkbase.com/apps/All/4.x/Add-On/app:OPSEC+LEA+for+Check+Point+%28Linux%29
还有一个:

  • www.splunkbase.com/apps/All/4.x/app:Benford's+法律+欺诈+检测+附加组件
  • www.splunkbase.com/apps/All/4.x/app:Benford%27s+法律+欺诈+检测+附加组件
还有一个:

  • www.splunkbase.com/apps/All/4.x/app:Benford%27s%20Law%20Fraud%20Detection%20Add-on
  • www.splunkbase.com/apps/All/4.x/app:Benford%27s+法律+欺诈+检测+附加组件
如果应用程序只看到这些URL的第二种形式,那么它将不会发送任何重定向,谷歌将能够索引页面

我是一个有重写规则的新手,从我读到的mod_rewrite做了一些自动编码/解码,这可能有助于或有损于我想做的事情,尽管我不确定


有没有关于重写规则以处理上述情况的建议?我同意为每个特殊角色制定一个规则,因为它们并不多,但是一个规则(如果可能的话)是理想的

mod_rewrite不是完成这类工作的最佳工具。因为使用mod_rewrite,一次只能替换固定数量的事件。但有可能:

RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?\ ]*)%20([^?\ ]*)
RewriteRule ^ /%1+%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?'\ ]*)'([^?'\ ]*)
RewriteRule ^ /%1\%27%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?(\ ]*)\(([^?(\ ]*)
RewriteRule ^ /%1\%28%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?)\ ]*)\)([^?)\ ]*)
RewriteRule ^ /%1\%29%2 [R=301,NE]
这将一次替换一个
%20
'
,或
,并以301重定向响应。因此,如果URL路径包含10个需要替换的字符,则需要10个重定向才能进行替换

由于这可能不是最佳解决方案,因此可以使用进行所有替换,但最后一次内部替换除外,并且只有最后一次外部替换使用重定向:

RewriteCond %{THE_REQUEST} ^[A-Z]+\ /(([^?%\ ]|%(2[1-9a-fA-F]|[013-9][0-9a-fA-F]))*)%20(([^?%\ ]|%(2[1-9a-fA-F]|[013-9][0-9a-fA-F]))*%20[^?\ ]*)
RewriteRule ^ /%1+%4 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?\ ]*)%20([^?\ ]*)[?\ ]
RewriteRule ^ /%1+%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?'\ ]*)'([^?'\ ]*'[^?\ ]*)
RewriteRule ^ /%1\%27%2 [N,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?'\ ]*)'([^?'\ ]*)[?\ ]
RewriteRule ^ /%1\%27%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?(\ ]*)\(([^?(\ ]*\([^?\ ]*)
RewriteRule ^ /%1\%28%2 [N,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?(\ ]*)\(([^?(\ ]*)[?\ ]
RewriteRule ^ /%1\%28%2 [R=301,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?)\ ]*)\)([^?)\ ]*\)[^?\ ]*)
RewriteRule ^ /%1\%29%2 [N,NE]
RewriteCond %{THE_REQUEST} ^[A-Z]+\ /([^?)\ ]*)\)([^?)\ ]*)[?\ ]
RewriteRule ^ /%1\%29%2 [R=301,NE]

但是使用N标志可能是危险的,因为它不会增加内部递归计数器,因此很容易导致无限递归。

该解决方案实际上可能相当简单,但由于使用了。我不确定它是否正确地处理了每一个案例(承认我有点怀疑它没有比这更多的工作),但我相信源代码应该这样做

还要记住,
REQUEST\u URI
的值不会被mod\u rewrite转换更新,因此如果应用程序依赖该值来确定请求的URL,那么所做的更改无论如何都不会可见

好消息是,这可以在.htaccess中完成,因此您可以选择保留主配置不变,如果这样对您更合适的话

RewriteEngine On

# Make sure this is only done once to avoid escaping the escapes...
RewriteCond %{ENV:REDIRECT_STATUS} ^$
# Check if we have anything to bother escaping (likely unnecessary...)
RewriteCond $0 [^\w]+
# Rewrite the entire URL by escaping the backreference
RewriteRule ^.*$ $0 [B]
那么,为什么需要使用
B
标志,而不是让mod_rewrite自动转义重写后的URL?当mod_rewrite自动转义URL时,它使用
ap_escape_uri
(由于某种原因,它显然已被转换为
ap_os_escape_path
的宏…),一个转义有限字符子集的函数。然而,
B
标志使用一个名为
escape\u uri
的内部模块函数,该函数是以PHP函数为模型的

模块中
escape_uri
的实现表明字母数字字符和下划线保持原样,空格转换为+,其他所有内容转换为其转义等价物。这似乎是你想要的行为,所以想必它应该起作用


如果没有,您可以选择设置一个外部程序,该程序可以将传入的URL转换为正确的格式。这需要操作Apache配置,而ReaveDad脚本可能会对服务器造成整体问题,因此,如果它可以避免的话,我认为这不是一个理想的解决方案。

您是否完全可以访问Apache配置,或者您仅限于一个HTTAccess友好的解决方案吗?我们可以完全访问Apache配置文件,虽然我怀疑我们的ops团队更喜欢微创的解决方案,但这似乎是我一直在寻找的答案。美好的嗯,在上述复杂程度上,要求开发团队重写重定向代码可能更容易。:-)另一个答案看起来更简单,所以我接受。但我喜欢你重复规则的一般想法——这可能不是我想要的解决方案,但在其他情况下可能有用。谢谢+1@Justin格兰特:可能是的。