特殊字符和 URL 重写

Posted

技术标签:

【中文标题】特殊字符和 URL 重写【英文标题】:Special Characters & URL Rewriting 【发布时间】:2012-08-20 03:31:47 【问题描述】:

我目前正在开发一个从暴雪社区 API 提取 JSON 数据并使用 php 解析它的应用程序。一切正常,直到我遇到一个名字中有特殊字符的角色。

为了提取角色数据,我需要知道他们的角色名称和他们所在的领域。

我通过 URL 将名称和领域传递到角色页面,并从那里使用该信息提取角色数据。

此时我的网址是这样的:

 http://localhost/guildtree/characters.php?realm=argent-dawn&name=Ankzu

此时,如果我尝试提取带有重音符号的字符的数据,我会被重定向到我的错误页面,因为它不是有效字符。

直到我开始 URL 重写,我才发现我的问题。我被重定向到我的错误页面,因为在某处特殊字符被替换为一些非常不稳定的字符。

使用我重写的新 URL,以下工作正常:

 http://localhost/guildtree/argent-dawn/ankzu

但是,名称中带有特殊字符的字符会导致错误消息。

 http://localhost/guildtree/argent-dawn/notúk

导致以下错误消息:

“未找到

在此服务器上找不到请求的 URL /guildtree/argent-dawn/notúk。"

正如您所见,ú 被 ú 取代,但是当我复制并粘贴 URL 时,ú 显示为 %C3%BA

据我了解,ú 显示为 ú 的原因是因为两个字节的 unicode ú 被压缩成两个一个字节的 ASCII 字符,导致显示 ú。

我已确保我的所有页面的标题中都有以下内容:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

为了让我的应用程序正常工作,我需要那些特殊字符才能正确显示,所以我需要 ú 实际显示为 ú,而不是显示为 ú 但实际上是 ú 或 %C3%BA。

正在从 URL 中提取字符名称,如下所示:

$charName = $_GET['name'];

是否可以对 $charName 进行编码以正确显示特殊字符?

我已经尝试了所有我能想到的方法并在 Google 上进行了搜索,但没有任何效果。

另外,因为我正在使用 URL 重写,所以重写规则允许这些特殊字符是什么?

这是我目前的重写规则:

 RewriteRule ^([a-zA-Z0-9_'-]+)/([a-zA-Z]+)$        characters.php?realm=$1&name=$2     [NC]

我知道 ([a-zA-Z]+) 根本不允许特殊字符,我目前一直在努力让特殊字符正确显示。如果我使用 ([a-zA-Z\ú]+) 它将工作并显示需要显示的页面。将 \ú 添加到规则中似乎是一种非常糟糕的方法,并且在使用重音字符的相应字符时并不总是有效。

任何帮助将不胜感激。如果您需要更多信息,请询问。

编辑:

将我的重写规则更改为以下允许正确提取信息,但会为我的 CSS 创建一个重定向循环。

 RewriteRule ^([a-zA-Z0-9_'-]+)/([^/]+)$        characters.php?realm=$1&name=$2 [NC]

例如,我的 CSS 被重定向到

http://localhost/guildtree/css/error

而不是

http://localhost/guildtree/css/style2.css

更新:

通过几个简单的测试:

$charName = $_GET['name'];
$charNameTEST = utf8_encode($charName);

会做出改变,但是当我将它应用到我的页面时,它仍然会出现:

“未找到

在此服务器上找不到请求的 URL /guildtree/argent-dawn/notúk。"

我认为现在的主要问题是 URL 重定向,因为当 JSON 数据具有重音字符时,它可以很好地解析。我只是不明白为什么它一直显示它在浏览器栏中的 guildtree/argent-dawn/notúk 上,但一直试图拉起 /guildtree/argent-dawn/notúk。

【问题讨论】:

【参考方案1】:

对于 URL,ú 不是有效字符。

无论您在何处链接用户名,都应该对其进行 URL 编码。

因此指向的正确 URL 是:

http://localhost/guildtree/argent-dawn/not%C3%BAk

您应该在 php 中将其打印为:

echo '<a href="http://localhost/guildtree/argent-dawn/'. urlencode($name) .'">Link</a>;

【讨论】:

有人直接输入网址怎么办? 您可能还需要考虑对用户名进行 ASCII 化。 example.com/guildtree/argent-dawn/notuk/ 而不是 example.com/guildtree/argent-dawn/not%C3%BAk。您的用户可能会发现它更容易。 example.com/guildtree/argent-dawn/notuk 和 example.com/guildtree/argent-dawn/notúk 会提取两组完全不同的数据,但角色名称必须准确。 @akari 不是最漂亮的解决方案,但在这种情况下,我会采取一个安全的解决方案并添加像http://localhost/guildtree/argent-dawn/5/notúk 这样的字符ID,并使用该数字进行数据库查找,其余的网址仅用于显示. @akari:如果用户直接输入 URL,这将无济于事。但 URL 标准不包括特殊字符。所以它实际上是浏览器中的一个错误,它无论如何都会发送 URL。【参考方案2】:

我想this question 可能会有你的答案。我自己没有尝试过,但据我所知,您需要将 RewriteRule 重写为:

RewriteRule ^([a-zA-Z0-9_'-]+)/([a-zA-Z]+)$        characters.php?realm=$1&name=$2     [NC,B]

B 标志将确保特殊字符是 URL 转义的,因此 $2 中 name 看到的值将是百分比编码的。由于您没有进行重定向,因此原始 Unicode 字符应该仍然是 URL 中显示的内容。

您还需要对正则表达式进行一些更改,以确保它与 unicode 字符匹配。我不确定那些会是什么。

还有更多关于unicode characters work in URLs over here的描述。

【讨论】:

我绑定了它,但它正在创建一个内部服务器错误。编辑:有一个错字,现在没有内部错误,但仍然无法正常工作。【参考方案3】:

要使其正常工作,您需要做两件事。

首先将其添加到您的 .htaccess 中

AddDefaultCharset On
AddDefaultCharset UTF-8
AddCharset UTF-8 .tpl
AddCharset UTF-8 .js
AddCharset UTF-8 .css
AddCharset UTF-8 .php

第二次更改重写规则中需要允许特殊字符为 (.*) 的部分,如下所示:

 RewriteRule ^([a-zA-Z0-9_'-]+)/(.*)$       characters.php?realm=$1&name=$2     [NC]

这会导致其他页面出现一些重定向循环,但我目前正在努力解决这个问题。

【讨论】:

以上是关于特殊字符和 URL 重写的主要内容,如果未能解决你的问题,请参考以下文章

URL中的特殊字符

iOS URL带特殊字符(汉字、空格等)导致图片加载失败

http请求特殊字符转码

URL编码:怎样读取特殊字符

Vue中js获取url参数,特殊字符的转译、逆转译

如何对bash中的所有字符(特殊和非特殊)进行url编码[重复]