用javascript编码URL?

Encode URL in JavaScript?

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

1
2
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)。在您的情况下,这应该有效:

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


您有三种选择:

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

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

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

但是在您的例子中,如果您想将一个URL传递到其他页面的GET参数中,您应该使用escapeencodeURIComponent,而不是encodeURI

请参阅堆栈溢出问题最佳实践:escape或encodeuri/encodeuricomponent以进行进一步讨论。


坚持使用encodeURIComponent()。函数encodeURI()不需要编码在URL中具有语义重要性的许多字符(例如""、"?",和"&;")。不推荐使用escape(),也不需要对"+"字符进行编码,这些字符将被解释为服务器上的编码空间(而且,正如这里其他人指出的,URL对非ASCII字符的编码不正确)。

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


最好的答案是对查询字符串中的值使用encodeURIComponent,而不是其他任何地方。

但是,我发现许多API都想用"+"替换"",因此我必须使用以下内容:

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

escape在不同的浏览器中实现不同,encodeURI不编码许多字符(如甚至/)——它被用于完整的uri/url而不破坏它——这不是非常有用或安全的。

正如@jochem在下面指出的那样,您可能希望在一个(每个)文件夹名上使用encodeURIComponent(),但是无论出于什么原因,这些API似乎不希望+在文件夹名中,所以简单的旧encodeURIComponent工作得很好。

例子:

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


如果您使用jquery,我将使用$.param方法。它将对象映射字段编码为值,这比对每个值调用转义方法更容易读取。

1
2
$.param({a:"1=2", b:"Test 1
<div class="
suo-content">[collapse title=""]<ul><li>我认为提供的例子就足够了。如果您需要关于api.jquery.com/jquery.param的更多信息</li><li>几乎每个人都使用jquery,我确实觉得使用它比使用encoreuricomponent更舒服。</li></ul>[/collapse]</div><hr><P>如前所述,要对URL进行编码,您有两个函数:</P>[cc lang="javascript"]encodeURI()

1
encodeURIComponent()

两者都存在的原因是,第一个保留URL的风险是留下太多的东西没有被捕获,而第二个则对所需的一切进行编码。

首先,您可以将新转义的URL复制到地址栏中(例如),这样它就可以工作了。但是,未转义的"&;s"会干扰字段分隔符,"="会干扰字段名称和值,"+"看起来像空格。但是对于简单的数据,当您想要保留所转义内容的URL性质时,这是可行的。

第二个问题是,为了确保字符串中的任何内容都不会与URL发生冲突,您需要做的所有事情。它会保留各种不重要的字符,使URL尽可能保持人类可读而不受干扰。以这种方式编码的URL如果不取消覆盖,将不再作为URL工作。

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

我很难找到使用encodeuri()的理由——我会把它留给更聪明的人。


EncodeUriComponent()是一种方法。

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

但是您应该记住,与PHP版本urlencode()有细微的区别,正如@cms所提到的,它不会对每个字符进行编码。http://phpjs.org/functions/urlencode/made js相当于phpencode()

1
2
3
4
5
6
7
8
9
10
11
12
13
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, '+');
}

Similar kind of thing I tried with normal javascript

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

为了防止双重编码,最好在编码之前对URL进行解码(例如,如果您处理的是用户输入的URL,可能已经进行了编码)。

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

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

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
$(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;
            }
        }
    });
});

现在我没有任何问题了,而且它很有魅力。


下面是encodeURIComponent()decodeURIComponent()JS内置函数的现场演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!DOCTYPE html>
<html>
  <head>
    <style>
      textarea{
        width:30%;
        height:100px;
      }
    </style>
   
      // 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;
      }
   
  </head>
  <body>
   
      <textarea id="txt1">Some text to decode
      </textarea>
   
   
      <input type="button" id="btnencode" value="Encode" onClick="encode()"/>
   
   
      <textarea id="txt2">
      </textarea>
   
    <br/>
   
      <textarea id="txt3">U29tZSB0ZXh0IHRvIGRlY29kZQ==
      </textarea>
   
   
      <input type="button" id="btndecode" value="Decode" onClick="decode()"/>
   
   
      <textarea id="txt4">
      </textarea>
   
  </body>
</html>


什么是URL编码:

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

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

在这个例子中,我们可以观察到除了字符串notEncoded之外的所有字符都用%符号编码。URL编码也被称为百分比编码,因为它用百分比来转义所有特殊字符。然后在这个%符号之后,每个特殊字符都有一个唯一的代码

我们为什么需要URL编码:

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

如何在JS中实现URL编码:

JS提供了一系列内置实用程序功能,我们可以使用这些功能轻松编码URL。这是两个方便的选项:

  • encodeURIComponent():接受一个uri的组件作为参数,并返回编码的uri字符串。
  • encodeURI():接受一个uri作为参数,并返回编码的uri字符串。
  • 示例和注意事项:

    注意不要将整个URL(包括方案,如https://)传入encodeURIComponent()。这实际上可以将其转换为一个不起作用的URL。例如:

    1
    2
    3
    4
    5
    6
    // 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不再正常工作。

    因此(顾名思义)使用:

  • encodeURIComponent在你想要编码的URL的某个部分上。
  • encodeURI在你想要编码的整个URL上。

  • 编码URL字符串

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        var url = $(location).attr('href'); //get current url
        //OR
        var url = 'folder/index.html?param=#23dd&noob=yes'; //or specify one
    </p>

    <wyn>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

    您可以使用esapi库并使用下面的函数对URL进行编码。函数的作用是,在对文本内容的其余部分进行编码时,"/"不会丢失为编码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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_自述