如何确定字符串是否已经过URL编码?

时间:2010-02-19 09:36:08

标签: java utf-8 url-encoding

我如何检查字符串是否已被编码?

例如,如果我对TEST==进行编码,则会得到TEST%3D%3D。如果我再次对最后一个字符串进行编码,我会得到TEST%253D%253D,如果它已经编码,我必须知道...

我已保存编码参数,我需要搜索它们。我不知道输入参数,它们是什么 - 编码与否,所以我必须知道在搜索之前是否必须对它们进行编码或解码。

11 个答案:

答案 0 :(得分:37)

解码,与原始相比。如果它确实不同,则原始编码。如果没有差异,则不对原始编码进行编码。但它仍然没有说明新解码的版本是否仍未编码。递归的好任务。

我希望你不能在urlencode中写一个quine,否则这个算法就会卡住。

答案 1 :(得分:15)

使用正则表达式检查您的字符串是否包含非法字符(即在URL编码的字符串中找不到的字符,如空格)。

答案 2 :(得分:4)

乔尔在软件上有一个解决方案 - http://www.joelonsoftware.com/articles/Wrong.html 或者您可以在字符串中添加一些前缀。

答案 3 :(得分:3)

尝试解码网址。如果生成的字符串比原始字符串短,则原始URL已经编码,否则您可以安全地对其进行编码(或者它未编码,或者甚至编码后的url保持原样,因此再次编码不会导致错误的URL )。下面是示例伪(受红宝石启发)代码:

# Returns encoded URL for any given URL after determining whether it is already encoded or not
    def escape(url)
      unescaped_url = URI.unescape(url)
      if (unescaped_url.length < url.length)
        return url
      else
        return URI.escape(url)
      end
    end

答案 4 :(得分:2)

除非你的琴弦符合某种模式,否则你无法确定,或者你跟踪你的琴弦。正如您自己所指出的,编码的字符串也可以编码,因此通过查看字符串本身无法100%确定。

答案 5 :(得分:1)

为了避免两次编码并生成错误(如OP所述),我们取消引用,然后再次引用,在Python中将是:

import urllib.parse
urllib.parse.unquote(str)
urllib.parse.quote(str)

答案 6 :(得分:0)

检查您的URL中是否包含可疑字符[1]。 候选人名单:

WHITE_SPACE ,", < , > , { , } , | , \ , ^ , ~ , [ , ] , .和`

我使用:

private static boolean isAlreadyEncoded(String passedUrl) {
        boolean isEncoded = true;
        if (passedUrl.matches(".*[\\ \"\\<\\>\\{\\}|\\\\^~\\[\\]].*")) {
                isEncoded = false;
        }
        return isEncoded;
}

对于实际编码,我继续:

https://stackoverflow.com/a/49796882/1485527

注意:即使您的网址不包含不安全的字符,您也可能希望应用该字符,例如Punnycode编码为主机名。因此,仍有大量空间可以进行其他检查。


[1]可在第2页的URL spec的“不安全”部分中找到候选列表。 据我了解,在编码检查中应省略'%'或'#',因为这些字符也可能出现在编码的URL中。

答案 7 :(得分:0)

如果您想确保字符串已正确编码(如果需要编码),只需再次解码并编码。

元代码:

100%_correctly_encoded_string = encode(decode(input_string))

已经编码的字符串将保持不变。未编码的字符串将被编码。仅包含允许使用网址的字符的字符串也将保持不变。

答案 8 :(得分:0)

根据规范(https://tools.ietf.org/html/rfc3986),所有URL 必须均以一个方案开头,后跟一个:

由于必须使用冒号作为方案和URI其余部分之间的分隔符,因此不会对任何包含冒号的字符串进行编码。

(这假设您将获得没有方案的不完整URI。)

因此,您可以测试字符串是否包含冒号,如果没有,则对其进行URL解码,如果该字符串包含冒号,则对原始字符串进行URL编码,如果不是,则检查字符串是否不同,如果相同,则再次进行URLdecode否则,它不是有效的URI。

如果您知道可以期望的方案,则可以使此循环更简单。

答案 9 :(得分:0)

由于this answer,我编写了一个函数(JS语言),该函数使用encodeURI仅对URL进行了一次编码,因此您可以调用该函数以确保仅对它进行一次编码,而无需知道如果该URL已经被编码。

ES6:

var getUrlEncoded = sURL => {
    if (decodeURI(sURL) === sURL) return encodeURI(sURL)
    return getUrlEncoded(decodeURI(sURL))
}

ES6之前的版本:

var getUrlEncoded = function(sURL) {
    if (decodeURI(sURL) === sURL) return encodeURI(sURL)
    return getUrlEncoded(decodeURI(sURL))
}

这里有一些测试,因此您可以看到URL仅被编码一次

getUrlEncoded("https://example.com/media/Screenshot27 UI Home.jpg")
//"https://example.com/media/Screenshot27%20UI%20Home.jpg"
getUrlEncoded(encodeURI("https://example.com/media/Screenshot27 UI Home.jpg"))
//"https://example.com/media/Screenshot27%20UI%20Home.jpg"
getUrlEncoded(encodeURI(encodeURI("https://example.com/media/Screenshot27 UI Home.jpg")))
//"https://example.com/media/Screenshot27%20UI%20Home.jpg"
getUrlEncoded(decodeURI("https://example.com/media/Screenshot27 UI Home.jpg"))
//"https://example.com/media/Screenshot27%20UI%20Home.jpg"
getUrlEncoded(decodeURI(decodeURI("https://example.com/media/Screenshot27 UI Home.jpg")))
//"https://example.com/media/Screenshot27%20UI%20Home.jpg"

答案 10 :(得分:0)

使用Spring UriComponentsBuilder:

import java.net.URI;
import org.springframework.web.util.UriComponentsBuilder;

private URI getProperlyEncodedUri(String uriString) {
    try {
        return URI.create(uriString);
    } catch (IllegalArgumentException e) {
        return UriComponentsBuilder.fromUriString(uriString).build().toUri();
    }
}