26

如何测试字符串是否经过 URL 编码?

以下哪种方法更好?

  • 在字符串中搜索将被编码的字符,哪些不是,如果存在则它没有被编码,或者
  • 使用我制作的类似这样的东西:

function is_urlEncoded($string){
 $test_string = $string;
 while(urldecode($test_string) != $test_string){
  $test_string = urldecode($test_string);
 }
 return (urlencode($test_string) == $string)?True:False; 
}

$t = "Hello World > how are you?";
if(is_urlEncoded($sreq)){
 print "Was Encoded.\n";
}else{
 print "Not Encoded.\n";
 print "Should be ".urlencode($sreq)."\n";
}

上面的代码有效,但在字符串被双重编码的情况下无效,如以下示例所示:

  • $t = "Hello%2BWorld%2B%253E%2Bhow%2Bare%2Byou%253F";
  • $t = "Hello+World%2B%253E%2Bhow%2Bare%2Byou%253F";
4

13 回答 13

39

我有一个技巧:

您可以这样做以防止双重编码。每次先解码然后再编码;

$string = urldecode($string);

然后再做

$string = urlencode($string);

以这种方式执行我们可以避免双重编码:)

于 2010-06-17T08:28:13.500 回答
19

这是我刚刚放在一起的东西。

if ( urlencode(urldecode($data)) === $data){
    echo 'string urlencoded';
} else {
    echo 'string is NOT urlencoded';
}
于 2014-01-18T15:34:37.960 回答
10

您永远无法确定字符串是否经过 URL 编码,或者它是否应该包含该序列%2B。相反,它可能取决于字符串的来源,即它是手工制作的还是来自某些应用程序。

最好在字符串中搜索将被编码的字符,哪些不是,如果存在则它没有被编码。

我认为这是一种更好的方法,因为它会处理以编程方式完成的事情(假设应用程序不会留下非编码字符)。

这里会令人困惑的一件事......从技术上讲,如果%“应该”出现在最终值中,则“应该”被编码,因为它是一个特殊字符。您可能必须结合您的方法来查找应该编码的字符以及验证字符串是否成功解码(如果没有找到)。

于 2009-10-28T14:58:12.790 回答
5

好吧,“url 编码”这个词有点模糊,也许简单的正则表达式检查就可以了

$is_encoded = preg_match('~%[0-9A-F]{2}~i', $string);
于 2009-10-28T14:57:00.440 回答
5

我认为没有万无一失的方法可以做到这一点。例如,考虑以下情况:

$t = "A+B";

那是一个 URL 编码为“A B”还是需要编码为“A%2BB”?

于 2009-10-28T14:56:28.023 回答
5

关于什么:

if (urldecode(trim($url)) == trim($url)) { $url_form = 'decoded'; }
  else { $url_form = 'encoded'; }

不适用于双重编码,但我想这超出了范围吗?

于 2011-11-11T22:21:18.427 回答
3

没有可靠的方法可以做到这一点,因为有些字符串在编码过程中保持不变,即“abc”是否编码?没有明确的答案。此外,正如您所遇到的,某些字符有多种编码......但是......

由于某些字符可能以多种方式编码,因此您的 decode-check-encode-check 方案失败。但是,对您的函数进行轻微修改应该是相当可靠的,只需检查解码器是否修改了字符串,如果是,则它已被编码。

当然这不会是万无一失的,因为 "10+20=30" 将返回 true(+ 被转换为空格),但我们实际上只是在做算术。我想这是你的计划试图反击的,很抱歉我认为没有完美的解决方案。

HTH。

编辑:
正如我在自己的评论中提到的(只是为了清楚起见在这里重申),一个很好的折衷办法可能是检查你的 url 中的无效字符(例如空格),如果有一些它没有编码。如果没有,请尝试解码并查看字符串是否更改。这仍然不能处理上面的算术(这是不可能的),但希望它就足够了。

于 2009-10-28T14:57:43.483 回答
3

@user187291 代码有效,只有在 + 未编码时才会失败。

我知道这是很老的帖子。但这对我有用。

$is_encoded = preg_match('~%[0-9A-F]{2}~i', $string);
if($is_encoded) {
 $string  = urlencode(urldecode(str_replace(['+','='], ['%2B','%3D'], $string)));
} else {
  $string = urlencode($string);
}
于 2015-01-07T13:15:27.230 回答
1

当您已经从 url 获取数据时,发送一个标记解码的变量。

?path=folder/new%20file.txt&decode=1
于 2011-04-03T00:12:27.357 回答
1

在我的情况下,我想检查一个完整的 URL 是否被编码,所以我已经知道 URL 必须包含 string https://,我所做的是检查字符串是否包含编码版本https://( https%3A%2F%2F) 以及是否没有t,然后我知道它没有被编码:

//make sure $completeUrl is encoded
if (strpos($completeUrl, urlencode('https://')) === false) {
    // not encoded, need to encode it
    $completeUrl = urlencode($completeUrl);
}

理论上,该解决方案可用于任何具有已编码字符的字符串,只要您知道字符串的一部分(https://在本例中)将始终存在于您要检查的内容中​​。

于 2020-06-26T10:22:59.090 回答
0

我正在使用以下测试来查看字符串是否已被 urlencoded:

if(urlencode($str) != str_replace(['%','+'], ['%25','%2B'], $str))

如果一个字符串已经被 urlencoded,唯一会被双重编码改变的字符是 % (它开始所有编码的字符串)和 + (它替换空格)。把它们改回来,你应该有原始字符串。

让我知道这是否适合您。

于 2014-03-18T16:03:05.900 回答
0

我发现。
网址例如:https://example.com/xD?foo=bar&uri=https%3A%2F%2Fexample.com%2FxD
您需要找到 $_GET['uri'] 是否已编码:

preg_match("/.*uri=(.*)&?.*/", $_SERVER['REQUEST_URI'], $r);
if (isset($_GET['uri']) && urldecode($r['1']) === $r['1']) {
  // Code Here if url is not encoded
}
于 2019-08-27T16:15:53.660 回答
-1

private static boolean isEncodedText(String val, String... encoding) throws UnsupportedEncodingException { String decodedText = URLDecoder.decode(val, TransformFetchConstants.DEFAULT_CHARSET);

    if(encoding != null && encoding.length > 0){
        decodedText = URLDecoder.decode(val, encoding[0]);
    }

    String encodedText =  URLEncoder.encode(decodedText);

    return encodedText.equalsIgnoreCase(val) || !decodedText.equalsIgnoreCase(val);

}
于 2015-05-24T17:30:06.347 回答