如何使用JavaScript安全地编码URL,以便将其放入GET字符串中?

var myUrl = "http://example.com/index.html?param=1&anotherParam=2";
var myOtherUrl = "http://example.com/index.html?url=" + myUrl;

我假设您需要在第二行编码myUrl变量?


当前回答

最好的答案是对查询字符串中的值使用encodeURIComponent(而不是其他)。

然而,我发现许多API都想用“+”替换“”,所以我不得不使用以下方法:

const value = encodeURIComponent(value).replace('%20','+');
const url = 'http://example.com?lang=en&key=' + value

escape在不同浏览器中的实现方式不同,encodeURI不编码许多字符(如#和甚至/)——它可以在完整的URI/URL上使用,而不会破坏它——这并不是非常有用或安全的。

正如@Jochem在下面指出的,您可能希望在(每个)文件夹名称上使用encodeURIComponent(),但无论出于什么原因,这些API似乎不希望在文件夹名称中使用+,所以普通的encodeURIComponents非常有用。

例子:

const escapedValue = encodeURIComponent(value).replace('%20','+');
const escapedFolder = encodeURIComponent('My Folder'); // no replace
const url = `http://example.com/${escapedFolder}/?myKey=${escapedValue}`;

其他回答

我用普通JavaScript做了类似的尝试:

function fixedEncodeURIComponent(str){
    return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
}

没有什么对我有用。我看到的只是登录页面的HTML,返回到客户端,代码为200。(最初是302,但相同的Ajax请求在另一个Ajax请求中加载登录页面,这应该是一个重定向,而不是加载登录页面的纯文本)。

在登录控制器中,我添加了以下行:

Response.Headers["land"] = "login";

在全局Ajax处理程序中,我这样做了:

$(function () {
    var $document = $(document);
    $document.ajaxSuccess(function (e, response, request) {
        var land = response.getResponseHeader('land');
        var redrUrl = '/login?ReturnUrl=' + encodeURIComponent(window.location);
        if(land) {
            if (land.toString() === 'login') {
                window.location = redrUrl;
            }
        }
    });
});

现在我没有任何问题,它就像一个魅力。

不要忘记用/g标志替换所有编码的“”

var myOtherUrl = "http://example.com/index.html?url=" + encodeURIComponent(myUrl).replace(/%20/g,'+');

如前所述,要对URL进行编码,您有两个函数:

encodeURI()

and

encodeURIComponent()

两者都存在的原因是,第一种方法保留了URL,但有可能留下太多未被屏蔽的内容,而第二种方法对所有需要的内容进行编码。

使用第一个,您可以将新转义的URL复制到地址栏中(例如),这样就可以了。然而,未转义的‘&’会干扰字段分隔符,‘=’会干扰域名和值,‘+’看起来像空格。但对于简单的数据,当您希望保留要转义的内容的URL性质时,这是有效的。

第二个是您需要做的一切,以确保字符串中没有任何内容干扰URL。它保留了各种不重要的字符,使URL尽可能保持可读性而不受干扰。以这种方式编码的URL将不再作为URL工作,而不会取消其标题。

因此,如果您可以花点时间,那么在添加名称/值对之前,您总是希望使用encodeURIComponent()对名称和值进行编码,然后再将其添加到查询字符串中。

我很难找到使用encodeURI()的理由——我将把这留给更聪明的人。

您可以使用ESAPI库并使用以下函数对URL进行编码。该函数确保在对其余文本内容进行编码时,“/”不会因编码而丢失:

function encodeUrl(url)
{
    String arr[] = url.split("/");
    String encodedUrl = "";
    for(int i = 0; i<arr.length; i++)
    {
        encodedUrl = encodedUrl + ESAPI.encoder().encodeForHTML(ESAPI.encoder().encodeForURL(arr[i]));
        if(i<arr.length-1) encodedUrl = encodedUrl + "/";
    }
    return url;
}