提问



如何使用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(str)encodeURI(str)

在你的情况下,这应该工作:


var myOtherUrl = 
       "http://example.com/index.html?url=" + encodeURIComponent(myUrl);

其它参考1


你有三个选择:



  • escape()不会编码:@*/+

  • encodeURI()不会编码:~!@#$&*()=:/,;?+'

  • encodeURIComponent()不会编码:~!*()'



但在你的情况下,如果你想将URL传递给其他页面的GET参数,你应该使用escapeencodeURIComponent,而不是encodeURI[39]


请参阅Stack Overflow问题最佳实践:escape,或encodeURI/encodeURIComponent 以供进一步讨论。

其它参考2


坚持encodeURIComponent()。函数encodeURI()不打算编码在URL中具有语义重要性的许多字符(例如#,?和&)。 escape()已弃用,并且不打算编码+字符,这些字符将被解释为服务器上的编码空格(并且,正如其他人所指出的那样,不能正确地对非ASCII字符进行URL编码) [41] [42] [43]


对其他地方encodeURI()encodeURIComponent()之间的区别有一个很好的解释。如果要对某些内容进行编码以便可以安全地将其作为URI的一个组件包含在内(例如作为查询字符串参数),则需要使用encodeURIComponent()

其它参考3


就个人而言,我发现很多API都想用+代替,所以我使用以下内容:


encodeURIComponent(value).replace(/%20/g,'+');


escape在不同的浏览器中实现不同,encodeURI不会编码URI中的大多数字符(如#和偶数/) - 它被用于完整的URI/URL没有破坏它。


注意:您将encodeURIComponent用于查询字符串的(不是字段/值名称,绝对不是整个URL)。如果您以任何其他方式执行此操作,它将不会编码像=,?和&这样的字符,可能会使您的查询字符串暴露。


例:


const escapedValue = encodeURIComponent(value).replace(/%20/g,'+');
const url = 'http://example.com/?myKey=' + escapedValue;

其它参考4


如果您使用的是jQuery,我会选择$.param方法。它对一个对象进行编码,将字段映射到值,这比在每个值上调用转义方法更容易阅读。[45]


$.param({a:"1=2", b:"Test 1"}) // gets a=1%3D2&b=Test+1

其它参考5


要编码URL,如前所述,您有两个功能:


encodeURI()





encodeURIComponent()


两者之所以存在的原因是,第一个保留URL的风险是留下太多未转义的东西,而第二个则编码所需的一切。


使用第一个,您可以将新转义的URL复制到地址栏(例如),它可以工作。然而,你的未转义的&会干扰字段分隔符,=会干扰字段名称和值,而+将看起来像空格。但是对于简单的数据,当你想保留你正在逃避的URL性质时,这是有效的。


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


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


我很难想出使用encodeURI()的理由 - 我会把它留给更聪明的人。

其它参考6


encodeURIComponent()是要走的路。


var myOtherUrl = "http://example.com/index.html?url=" + encodeURIComponent(myUrl);


但是你应该记住,与php版本urlencode()存在细微的差别,并且如提到的@CMS,它不会对每个char进行编码。 http://phpjs.org/functions/urlencode/上的家伙使js等同于phpencode():[46]


function urlencode(str) {
  str = (str + '')
    .toString();

  // Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current
  // PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following.
  return encodeURIComponent(str)
    .replace(/!/g, '%21')
    .replace(/'/g, '%27')
    .replace(/\(/g, '%28')
    .
  replace(/\)/g, '%29')
    .replace(/\*/g, '%2A')
    .replace(/%20/g, '+');
}

其它参考7


我用普通的javascript试过类似的东西


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

其它参考8


为了防止双重编码,在编码之前解码网址是个好主意(例如,如果您正在处理用户输入的网址,可能已经编码)。


假设我们有abc%20xyz 123作为输入(一个空格已经编码):


encodeURI("abc%20xyz 123")            //   wrong: "abc%2520xyz%20123"
encodeURI(decodeURI("abc%20xyz 123")) // correct: "abc%20xyz%20123"

其它参考9


没有什么对我有用。我所看到的只是登录页面的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;
            }
        }
    });
});


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

其它参考10


编码网址字符串
    
    var url = $(location).attr('href'); //get current url
    //OR
    var url = 'folder/index.html?param=#23dd&noob=yes'; //or specify one

var encodedUrl = encodeURIComponent(url); console.log(encodedUrl); //outputs folder%2Findex.html%3Fparam%3D%2323dd%26noob%3Dyes for more info go http://www.sitepoint.com/jquery-decode-url-string

其它参考11


您可以使用esapi库并使用以下函数对您的网址进行编码。该函数承受/不会丢失编码,而其余的文本内容编码:


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;
}


https://www.owasp.org/index.php/ESAPI_JavaScript_Readme[47]