在JavaScript中编码URL?

时间:2008-12-02 02:37:08

标签: javascript url encoding

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

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

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

21 个答案:

答案 0 :(得分:2652)

查看内置功能encodeURIComponent(str)encodeURI(str) 在你的情况下,这应该工作:

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

答案 1 :(得分:1455)

您有三种选择:

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

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

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

但在您的情况下,如果您想将URL传递到其他网页的GET参数,则应使用escapeencodeURIComponent,而不是{{} 1}}。

有关进一步讨论,请参阅Stack Overflow问题 Best practice: escape, or encodeURI / encodeURIComponent

答案 2 :(得分:171)

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

其他地方有一个不错的explanation of the difference between encodeURI() and encodeURIComponent()。如果要对某些内容进行编码以便可以安全地将其作为URI的一个组件包含在内(例如作为查询字符串参数),则需要使用encodeURIComponent()

答案 3 :(得分:76)

最佳答案是在查询字符串中使用 encodeURIComponent(以及其他任何地方)。

但是,我发现很多API都想用“+”代替“”,所以我不得不使用以下内容:

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

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

正如@Jochem在下面指出的那样,您可能希望在(每个)文件夹名称上使用encodeURIComponent(),但无论出于何种原因,这些API似乎不希望在文件夹名称中+朴素的encodeURIComponent效果很好。

示例:

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

答案 4 :(得分:39)

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

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

答案 5 :(得分:10)

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

encodeURI()

encodeURIComponent()

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

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

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

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

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

答案 6 :(得分:9)

encodeURIComponent()是要走的路。

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

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

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 :(得分:5)

我尝试过普通javascript的类似事情

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

答案 8 :(得分:4)

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

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

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

答案 9 :(得分:3)

对我来说没有任何作用。我所看到的只是登录页面的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 :(得分:2)

编码网址字符串     

    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 :(得分:2)

什么是URL编码:

当URL中包含特殊字符时,应对URL进行编码。例如:

console.log(encodeURIComponent('?notEncoded=&+'));

在此示例中,我们可以看到除字符串notEncoded以外的所有字符都用%符号编码。 URL编码也称为百分比编码,因为它会转义带有%的所有特殊字符。然后,在此%符号后,每个特殊字符都有一个唯一的代码

我们为什么需要URL编码:

某些字符在URL字符串中具有特殊值。例如,?字符表示查询字符串的开头。为了成功地在Web上定位资源,必须区分字符是字符串的一部分还是url结构的一部分。

我们如何在JS中实现URL编码:

JS提供了许多内置实用程序功能,我们可以使用它们轻松地对URL进行编码。这是两个方便的选项:

  1. encodeURIComponent():将URI的一部分作为参数,并返回编码后的URI字符串。
  2. encodeURI():将URI作为参数并返回已编码的URI字符串。

示例和警告:

请注意不要将整个URL(包括方案,例如https://)传递到encodeURIComponent()中。实际上,这可以将其转换为无法正常使用的URL。例如:

// for a whole URI don't use encodeURIComponent it will transform
// the / characters and the URL won't fucntion properly
console.log(encodeURIComponent("http://www.random.com/specials&char.html"));

// instead use encodeURI for whole URL's
console.log(encodeURI("http://www.random.com/specials&char.html"));

我们可以看到,如果将整个URL放在encodeURIComponent中,则前斜杠(/)也将转换为特殊字符。这将导致URL无法正常运行。

因此(顾名思义)使用:

  1. encodeURIComponent在您要编码的URL的特定部分上。
  2. encodeURI在您要编码的整个URL上。

答案 12 :(得分:2)

以下是encodeURIComponent()decodeURIComponent()的JS内置函数中的LIVE DEMO

<!DOCTYPE html>
<html>
  <head>
    <style>
      textarea{
        width:30%;
        height:100px;
      }
    </style>
    <script>
      // encode string to base64
      function encode()
      {
        var txt = document.getElementById("txt1").value;
        var result = btoa(txt);
        document.getElementById("txt2").value = result;
      }
      // decode base64 back to original string
      function decode()
      {
        var txt = document.getElementById("txt3").value;
        var result = atob(txt);
        document.getElementById("txt4").value = result;
      }
    </script>
  </head>
  <body>
    <div>
      <textarea id="txt1">Some text to decode
      </textarea>
    </div>
    <div>
      <input type="button" id="btnencode" value="Encode" onClick="encode()"/>
    </div>
    <div>
      <textarea id="txt2">
      </textarea>
    </div>
    <br/>
    <div>
      <textarea id="txt3">U29tZSB0ZXh0IHRvIGRlY29kZQ==
      </textarea>
    </div>
    <div>
      <input type="button" id="btndecode" value="Decode" onClick="decode()"/>
    </div>
    <div>
      <textarea id="txt4">
      </textarea>
    </div>
  </body>
</html>

答案 13 :(得分:2)

您不应直接使用encodeURIComponent()

https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/panorama-galleryconnect

sub-delims =“!” /“ $” /“&” /“'” /“(” /“)” /“ *” /“ +” /“,” /“;” /“ =”

保留字符的目的是提供一组与URI中的其他数据区分开的定界字符。

encodeURIComponent()不会转义RFC3986中URI定义中的这些保留字符。

Take a look at RFC3986: Uniform Resource Identifier (URI): Generic Syntax

为了严格遵守RFC 3986(保留!,',(,)和*),即使这些字符没有正式的URI分隔用法,也可以安全地使用以下字符:

使用MDN Web文档功能...

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}

答案 14 :(得分:1)

您可以使用esapi库并使用以下功能对您的网址进行编码。该功能可以承受&#39; /&#39;在编码的其余文本内容时,编码不会丢失:

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

答案 15 :(得分:1)

使用fixedEncodeURIComponent功能严格遵守RFC 3986

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}

答案 16 :(得分:0)

以我的拙见,对查询参数进行编码的最优雅的方法是使用

这样的参数创建对象
const queryParams = { param1: 'value1', param2: 'value2' }

,然后使用:

对其进行编码
const queryString = new URLSearchParams(queryParams).toString()

在此答案中提到: https://stackoverflow.com/a/53171438/7284582

答案 17 :(得分:0)

性能

今天(2020.06.12)我在浏览器Chrome 83.0,Safari 13.1和Firefox 77.0的MacOs HighSierra 10.13.6上对所选解决方案进行了速度测试。此结果对于大量的URL编码很有用。

结论

  • encodeURI(B)似乎最快,但不是recommended for url-s
  • escape(A)是快速的跨浏览器解决方案
  • MDN建议的
  • 解决方案F是中等速度
  • 解决方案D最慢

enter image description here

详细信息

有关解决方案 A B C D E F 我进行了两次测试

  • 简短网址-50个字符-您可以运行HERE
  • 对于长网址-1M字符-您可以运行它HERE

function A(url) {
	return escape(url);
}

function B(url) {
	return encodeURI(url);
}

function C(url) {
	return encodeURIComponent(url);
}

function D(url) {
	return new URLSearchParams({url}).toString();
}

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

function F(url) {
  return encodeURIComponent(url).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}



// ----------
// TEST
// ----------

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

[A,B,C,D,E,F]
  .forEach(f=> console.log(`${f.name} ?url=${f(myUrl).replace(/^url=/,'')}`));
This snippet only presents code of choosen solutions

Chrome的示例结果

enter image description here

答案 18 :(得分:0)

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

不要忘记/ g标志来替换所有编码的''

答案 19 :(得分:0)

我总是使用它来编码URL的内容。这是完全安全的,因为即使不需要编码,它也会对每个字符进行编码。

function urlEncode(text) {
    encoded = '';
    for (let char of text) {
        encoded += '%' + char.charCodeAt(0).toString(16);
    }
    return encoded;
}

答案 20 :(得分:0)

我认为现在到 2021 年真的很安全,您应该始终考虑使用 URL() interface 构建您的网址。它会为您完成大部分工作。所以来到你的代码,

const baseURL = 'http://example.com/index.html';

const myUrl = new URL(baseURL);
myUrl.searchParams.append('param', '1');
myUrl.searchParams.append('anotherParam', '2');

const myOtherUrl = new URL(baseURL);
myOtherUrl.searchParams.append('url', myUrl.href);

console.log(myUrl.href); // Outputs: http://example.com/index.html?param=1&anotherParam=2
console.log(myOtherUrl.href); // Outputs: http://example.com/index.html?url=http%3A%2F%2Fexample.com%2Findex.html%3Fparam%3D1%26anotherParam%3D2

const params = new URLSearchParams(myOtherUrl.search);

console.log(params.get('url')); // Outputs: http://example.com/index.html?param=1&anotherParam=2

这样的事情肯定不会失败。