【问题标题】:urlencoded Forward slash is breaking URLurlencoded 正斜杠正在破坏 URL
【发布时间】:2011-03-15 04:40:25
【问题描述】:

关于系统

我的项目中有这种格式的 URL:-

http://project_name/browse_by_exam/type/tutor_search/keyword/class/new_search/1/search_exam/0/search_subject/0

关键字/类对表示使用“类”关键字进行搜索。

我有一个为项目中的每个模块执行的通用 index.php 文件。从 URL 中删除 index.php 只有一个重写规则:-

RewriteCond $1 !^(index\.php|resources|robots\.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L,QSA]

我在准备搜索 URL 时使用 urlencode(),在读取搜索 URL 时使用 urldecode()。

问题

只有正斜杠字符会破坏 URL,导致 404 页面未找到错误。 例如,如果我搜索 one/two,则 URL 是

http://project_name/browse_by_exam/type/tutor_search/keyword/one%2Ftwo/new_search/1/search_exam/0/search_subject/0/page_sort/

我该如何解决这个问题?我需要将 index.php 隐藏在 URL 中。否则,如果不需要,正斜杠就没有问题,我可以使用这个 URL:-

http://project_name/index.php?browse_by_exam/type/tutor_search/keyword/one
%2Ftwo/new_search/1/search_exam/0/search_subject/0

【问题讨论】:

  • 我觉得最好有这样的 URL:- http://project_name/browse_by_exam?type/tutor_search/keyword/class %2Fnew/new_search/1/search_exam/0/search_subject/0 这样我就摆脱了由 &param1=value1&param2=value2 约定引起的可读性困难,而且我还可以允许正斜杠(现在在查询字符串部分使用?)我会避免使用AllowEncodedSlashes,因为Bobince 说Also some tools or spiders might get confused by it. Although %2F to mean / in a path part is correct as per the standard, most of the web avoids it. url .htaccess url-routing
  • 如果使用这种方式可以使用 %2F ?param1=value1&param2=value%2Fvalue 但如果使用 /param1=value1/param2=value%2Fvalue 则会抛出错误。

标签: .htaccess url-rewriting http-status-code-404 url-encoding


【解决方案1】:

出于安全原因,Apache 拒绝路径部分中带有 %2F 的所有 URL:由于 PATH_INFO 环境变量,脚本无法正常(即不重写)区分 %2F/自动进行 URL 解码(这很愚蠢,但它是 CGI 规范的长期组成部分,因此无能为力)。

您可以使用 AllowEncodedSlashes 指令关闭此功能,但请注意,其他 Web 服务器仍将禁止此功能(没有关闭该功能的选项),并且其他字符也可能是禁忌(例如 %5C ),并且特别是 %00 将始终被 Apache 和 IIS 阻止。因此,如果您的应用程序依赖于能够在路径部分包含 %2F 或其他字符,您将限制您的兼容性/部署选项。

我在准备搜索 URL 时使用 urlencode()

您应该使用rawurlencode(),而不是urlencode() 来转义路径部分。 urlencode() 命名错误,它实际上是针对查询字符串或 POST 请求正文中的 application/x-www-form-urlencoded 数据,而不是针对 URL 的其他部分。

不同之处在于+ 并不意味着路径部分中的空间。 rawurlencode() 将正确生成 %20,这将适用于表单编码数据和 URL 的其他部分。

【讨论】:

  • 啊,这就是斜线被拒绝的原因。完善的诊断和治疗。
  • +1 我尝试在他的一个其他问题中解释其中的一些内容,但你做的比我能做的更连贯。
  • 嗨 Bobince,rawurlencode() 也将正斜杠转换为 %2F,这仍然会破坏我的 URL。我实际上不明白rawurlencode() 是如何解决我的问题的。
  • 它没有,这是+%20 的一个附带问题。修复程序是AllowEncodedSlashes,尽管依赖它会降低您部署的可能性(即,您无法在 IIS 上部署它,而其他用户(如果有的话)将无法部署它,如果他们使用共享主机无法访问httpd.conf)。还有一些工具或蜘蛛可能会被它弄糊涂。尽管按照标准,路径部分中的%2F 表示/ 是正确的,但大多数网络都避免使用它。
  • 是的,查询字符串中必须允许任何编码字节序列。虽然根据 URL RFC,任何编码字节在路径组件中在技术上都是有效的,但由于路径部分传统上用于文件名,服务器会遇到其中一些问题。除了%00%2F%5C 之外,IIS 还会在路径中的非 ASCII 字节序列不是有效的 UTF-8 序列时给您带来麻烦。
【解决方案2】:

在 Apache 中,AllowEncodedSlashes On 会阻止请求立即被 404 拒绝。

关于如何解决这个问题的另一个想法。

【讨论】:

    【解决方案3】:

    在我的主机帐户上,此问题是由自动为所有帐户设置的 ModSecurity 规则引起的。在我报告此问题后,他们的管理员迅速为我的帐户删除了此规则。

    【讨论】:

      【解决方案4】:

      如果这样使用,你可以使用%2F
      ?param1=value1&param2=value%2Fvalue

      但是如果你使用/param1=value1/param2=value%2Fvalue,它会抛出一个错误。

      【讨论】:

        【解决方案5】:
        $encoded_url = str_replace('%2F', '/', urlencode($url));
        

        【讨论】:

          【解决方案6】:

          此问题的标准解决方案是通过将可能包含斜杠的参数设置为 url 中的最后一个参数来允许使用斜杠。

          对于产品代码网址,您将拥有...

          mysite.com/product/details/PR12345/22
          

          对于您想要的搜索词

          http://project/search_exam/0/search_subject/0/keyword/Psychology/Management
          

          (这里的关键词是心理学/管理)

          处理第一个“命名”参数然后将剩余的参数连接为产品代码或关键字并不是大量工作。

          一些框架在其路由定义中内置了此功能。

          这不适用于涉及我包含斜杠的两个参数的用例。

          【讨论】:

            【解决方案7】:

            url编码后用%252F替换%2F

            PHP

            function custom_http_build_query($query=array()){
            
                return str_replace('%2F','%252F', http_build_query($query));
            }
            

            通过 htaccess 处理请求

            .htaccess

            RewriteCond %{REQUEST_URI} ^(.*?)(%252F)(.*?)$ [NC]
            RewriteRule . %1/%3 [R=301,L,NE]
            

            资源

            http://www.leakon.com/archives/865

            【讨论】:

            • 非常感谢,我的问题是没有NE标志。
            【解决方案8】:

            我对带有正斜杠的 URL 部分使用 javascript encodeURI() 函数,应该将其视为字符而不是 http 地址。 例如:

            "/api/activites/" + encodeURI("?categorie=assemblage&nom=Manipulation/Finition")
            

            http://www.w3schools.com/tags/ref_urlencode.asp

            【讨论】:

            • 问题在于在将 URI 编码为 %2F 后对其进行处理 - 请参阅已接受的答案 Apache denies all URLs with %2F in the path part
            【解决方案9】:

            使用不同的字符并替换服务器端的斜杠

            例如Drupal.org 使用 %21(感叹号字符!)来表示 url 参数中的斜线。

            以下两个链接都有效:

            https://api.drupal.org/api/drupal/includes%21common.inc/7

            https://api.drupal.org/api/drupal/includes!common.inc/7

            如果您担心字符可能与参数中的字符发生冲突,请使用字符组合。

            所以你的网址是 http://project_name/browse_by_exam/type/tutor_search/keyword/one_-!two/new_search/1/search_exam/0/search_subject/0

            用js改出来,转回斜线服务器端。

            【讨论】:

              【解决方案10】:

              我在 url get param 中遇到了同样的问题,在我的情况下,以下 php 代码有效:

              $value = "hello/world"
              $value = str_replace('/', '/', $value;?>
              $value = urlencode($value);?>
              # $value is now hello%26%2347%3Bworld
              

              我首先将斜杠替换为 html 实体,然后进行 url 编码。

              【讨论】:

                【解决方案11】:

                我通过使用 2 个自定义函数解决了这个问题:

                function slash_replace($query){
                
                    return str_replace('/','_', $query);
                }
                
                function slash_unreplace($query){
                
                    return str_replace('_','/', $query);
                }
                

                所以编码我可以调用:

                rawurlencode(slash_replace($param))
                

                解码我可以调用

                slash_unreplace(rawurldecode($param);
                

                干杯!

                【讨论】:

                  【解决方案12】:

                  使用base64_encode对我来说很简单

                  $term = base64_encode($term) 
                  $url = $youurl.'?term='.$term
                  

                  解码后

                  $term = base64_decode($['GET']['term'])
                  

                  这样编码“/”和“\”

                  【讨论】:

                    【解决方案13】:

                    这是我的拙见。 !!!!别 !!!!更改服务器上的设置以使您的参数正常工作。当您更改服务器时,这是一个等待发生的定时炸弹。

                    我发现的最佳方法是将参数转换为 base 64 编码。所以在我的例子中,我从 Angular 调用一个 php 服务并传递一个可以包含任何值的参数。

                    所以我在客户端的打字稿代码如下所示:

                        private encodeParameter(parm:string){
                        if (!parm){
                            return null;
                        }
                        return btoa(parm);
                    }
                    

                    并在php中检索参数:

                        $item_name = $request->getAttribute('item_name');
                        $item_name = base64_decode($item_name); 
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2018-05-30
                      • 2010-09-23
                      • 1970-01-01
                      • 2015-08-11
                      • 1970-01-01
                      • 1970-01-01
                      • 2015-03-26
                      相关资源
                      最近更新 更多