用JavaScript编码URL?


2469

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

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

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




1
您可以在此处使用此工具:phillihp.com/toolz/url-encode-decode
phillihp 2012年

2
encodeURIComponent()
安德鲁

Answers:


2791

签出内置函数encodeURIComponent(str)encodeURI(str)
在您的情况下,这应该起作用:

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

12
添加@cms给出的解释如何?escape也是有效的选择。
hitautodestruct 2012年

11
根据@CMS的说法encodeURI,URL编码并不是很安全。
如果不是2013年

13
@AnaelFavre因为它的目的是编码整个URL,即不允许的字符,例如:/@等不使用可互换的这2种方法,你必须知道你的编码使用正确的方法是什么。
Buu Nguyen


如前所述在此页面上的另一种答案这个网站很好地详细介绍使用这种方法的原因
布拉德·帕克斯

1520

您有三种选择:

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

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

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

但在您的情况下,如果要将URL传递到GET其他页面的参数中,则应使用escapeencodeURIComponent,但不能使用encodeURI

有关进一步的讨论请参见堆栈溢出问题最佳实践:转义,或encodeURI / encodeURIComponent


76
转义使用的字符编码是可变的。坚持使用UTF-8的encodeURI和encodeURIComponent。
erickson

6
小心。该转义将非ASCII字符转换为其Unicode转义序列,例如%uxxx
opteronn

4
我正在使用encodeURIComponent,注意到它不会对管道字符进行编码。
kevzettler 2011年

15
@kevzettler-为什么要这样做?管道在URI中不具有语义重要性。
尼克

4
@GiovanniP:允许输入德语,法语,日语,中文,阿拉伯字符并通过GET或POST传递这些参数的人。

180

坚持下去encodeURIComponent()。该函数encodeURI()不会麻烦编码许多在URL中具有语义重要性的字符(例如“#”,“?”和“&”)。escape()已弃用,并且不会费心地对“ +”字符进行编码,后者将被解释为服务器上的编码空格(并且,如此处其他人所指出的那样,不会正确地对非ASCII字符进行URL编码)。

有一个很好的区别的解释encodeURI()encodeURIComponent()其他地方。如果您希望对某些内容进行编码,以便可以安全地将其作为URI的组成部分(例如,作为查询字符串参数),请使用encodeURIComponent()


83

最好的答案是使用encodeURIComponent的查询字符串(和其他地方)。

但是,我发现许多API都希望将“”替换为“ +”,因此我不得不使用以下内容:

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

escape在不同的浏览器中以不同的方式实现,encodeURI并且不对许多字符进行编码(例如#甚至是/)-使其用于完整的URI / URL而不会破坏它-这不是超级有用或安全的做法。

就像@Jochem在下面指出的那样,您可能想encodeURIComponent()在一个(每个)文件夹名称上使用,但是由于任何原因,这些API似乎都不希望+在文件夹名称中使用,所以普通的旧版本encodeURIComponent效果很好。

例:

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

22
请注意,您只能在第一个问号(URL的“查询”部分)后用+符号替换%20。假设我要浏览到http://somedomain/this dir has spaces/info.php?a=this has also spaces。应该将其转换为:http://somedomain/this%20dir%20has%spaces/info.php?a=this%20has%20also%20spaces但是许多实现允许将查询字符串中的'%20'替换为'+'。但是,您不能在URL的路径部分中将“%20”替换为“ +”,这将导致未找到错误,除非您的目录中带有+而不是空格。
Jochem Kuijpers

@Jochem Kuijpers,绝对不会在目录中添加“ +”。我只会将此应用到查询参数值本身(或键(如果需要)),而不是整个URL甚至整个查询字符串。
瑞安·泰勒

我会替换值而不是编码结果
njzk2 2014年

1
不幸的encodeURIComponent('+')%2B,@ njzk2 会给你,所以你必须使用两个正则表达式...我想这是为什么这样起作用的原因,因为最后的'+'是''编码不同。
瑞安·泰勒

没有理由将%20转换为“ +”。ASCII空间的有效转义序列为%20,而不是RFC 3986(tools.ietf.org/html/rfc3986)中未提及的“ +” 。在1990年代使用了“ +”;现在已过时,仅出于传统原因才受支持。不要使用它。
xhienne

40

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

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

我认为提供的示例就足够了。如果您需要有关api.jquery.com/jquery.param
Maksym Kozlenko 2015年

几乎每个人都使用jQuery,我确实对此感到更舒服,而不是使用encoreURIComponent
Cyril Duchon-Doris

12

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('!', '%21')
    .replace('\'', '%27')
    .replace('(', '%28')
    .replace(')', '%29')
    .replace('*', '%2A')
    .replace('%20', '+');
}

10

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

encodeURI()

encodeURIComponent()

两者都存在的原因是,第一个保留了URL,却有使太多内容无法逃脱的风险,而第二个则编码了所需的所有内容。

对于第一个,您可以将新转义的URL复制到地址栏中(例如),它可以工作。但是,未转义的“&”会干扰字段定界符,“ =”会干扰字段名和值,而“ +”则看起来像空格。但是对于简单数据,当您想要保留要转义的URL的本性时,此方法有效。

第二个是您需要做的所有事情,以确保字符串中的任何内容都不会干扰URL。它保留了各种不重要的字符,从而使URL尽可能保持人类可读性,而不会受到干扰。如果不进行转义,则以这种方式编码的URL将不再用作URL。

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

我在艰难时期想出使用encodeURI()的理由-我会将其留给聪明的人。


5

我尝试使用普通javascript进行的类似操作

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

5

优雅的方式

以我的拙见,对查询参数进行编码的最优雅的方法是创建一个具有以下参数的对象

const queryParams = { param1: 'value1', param2: 'value2' }

然后使用以下代码对其进行编码:

const queryString = new URLSearchParams(queryParams).toString()

如此答案中所述:https : //stackoverflow.com/a/53171438/7284582


4

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

可以说我们有abc%20xyz 123输入(已经编码了一个空格):

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

4

什么是网址编码:

如果网址中包含特殊字符,则应对网址进行编码。例如:

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上。

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

现在,我没有任何问题,它就像一个护身符。


2

编码URL字符串

    var url = $ 位置)。attr 'href' ); //获取当前网址// OR var url = 'folder / index.html?param =#23dd&noob = yes' ; //或指定一个 
    
      

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

2

这里有一个现场演示encodeURIComponent()decodeURIComponent()内置函数JS:

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

1

您可以使用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;
}

https://www.owasp.org/index.php/ESAPI_JavaScript_Readme


1

使用fixedEncodeURIComponent功能严格遵守RFC 3986

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

1

您不应该encodeURIComponent()直接使用。

看看RFC3986:统一资源标识符(URI):通用语法

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

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

RFC3986中URI定义中的这些保留字符不会被逸出encodeURIComponent()

MDN Web文档:encodeURIComponent()

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

使用MDN Web文档功能...

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.