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

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


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

评论

尝试查看encodeURI()和decodeURI()。

请参阅JavaScript urlencode函数。

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

encodeURIComponent()

#1 楼

请查看内置函数encodeURIComponent(str)和encodeURI(str)。
在您的情况下,这应该可以工作:

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


评论


添加@cms给出的解释如何?转义也是有效的选择。

–hitautodestruct
2012年10月28日上午11:36

根据@CMS编码,URL编码并不是真正安全的。

–如果不是
13年1月1日在16:35

@AnaelFavre,因为它是要对整个URL进行编码,不允许使用:,/,@等字符。这两种方法不可互换使用,必须使用正确的方法才能知道要编码的内容。

–阮布(Buu Nguyen)
2013年3月6日19:32



另请参阅developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…和developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

–麦恰(MichałPerłakowski)
16年1月2日,18:15

如本页另一答案所述,该网站很好地详细说明了使用此方法的原因

–布拉德公园
16年5月6日在13:07

#2 楼

您有以下三种选择:


escape()无法编码:@*/+
encodeURI()无法编码:~!@#$&*()=:/,;?+'
encodeURIComponent()无法编码:~!*()'

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

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

评论


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

– erickson
08年12月2日在4:55

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

–opteronn
10 Mar 5 '10在20:10



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

–kevzettler
2011年1月30日5:05

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

–nickf
2011年1月31日上午11:36

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

–曾
2013年9月4日14:43在

#3 楼

坚持encodeURIComponent()。函数encodeURI()不会麻烦编码许多在URL中具有语义重要性的字符(例如“#”,“?”和“&”)。 escape()已被弃用,并且不会费心地对“ +”字符进行编码,后者将被解释为服务器上的编码空格(并且,如此处其他人所指出的那样,不会正确地对非ASCII字符进行URL编码)。 >
其他地方对encodeURI()encodeURIComponent()之间的区别有很好的解释。如果您想对某些内容进行编码以便可以安全地将其作为URI的组成部分(例如,作为查询字符串参数),请使用encodeURIComponent()

#4 楼

最好的答案是对查询字符串中的值使用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效果很好。

示例:

评论


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

– Jochem Kuijpers
13年1月20日在1:08

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

–瑞安·泰勒(Ryan Taylor)
13年7月19日在22:16

我会替换为值,而不是编码的结果

– njzk2
2014年6月2日18:11

@ njzk2不幸的是,encodeURIComponent('+')会给您%2B,因此您必须使用两个正则表达式...我想这是可行的原因,因为'+'是''的结尾编码不同。

–瑞安·泰勒(Ryan Taylor)
2014年6月2日,18:17



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

– xhienne
19 Mar 26 '19在12:25



#5 楼

我建议使用qs npm包
qs.stringify({a:"1=2", b:"Test 1"}); // gets a=1%3D2&b=Test+1

使用JS对象更容易,并且它为所有参数提供正确的URL编码
如果您使用的是jQuery,我会使用$.param方法。它使用URL编码将对象映射到值的字段,这比在每个值上调用转义方法更容易阅读。
$.param({a:"1=2", b:"Test 1"}) // gets a=1%3D2&b=Test+1


评论


我认为提供的示例就足够了。如果您需要有关api.jquery.com/jquery.param上$ .param的更多信息,

–马克斯·科兹连科(Maksym Kozlenko)
2015年9月10日在10:21



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

–西里尔·杜尚(Cyril Duchon-Doris)
17年1月4日在16:36

#6 楼



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', '+');
}


#7 楼

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

encodeURI()




encodeURIComponent()


两者都存在的原因是,第一个保留了URL,却有使太多内容无法转义的风险,而第二个则编码了所需的所有内容。栏(例如),它将起作用。但是,未转义的“&”会干扰字段定界符,“ =”会干扰字段名和值,而“ +”则看起来像空格。但是对于简单数据,当您想要保留要转义的URL的本性时,这是可行的。它保留了各种不重要的字符,从而使URL尽可能保持可读性,而不会受到干扰。这样编码的URL将无法在不转义的情况下用作URL。在将名称和值添加到查询字符串中之前,都需要使用此函数。

我很难说出使用encodeURI()的原因-我将其留给更聪明的人。

#8 楼

优雅的方式

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

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


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

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


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

#9 楼

我用普通javascript尝试过的类似方法

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


#10 楼

什么是URL编码:

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




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





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

为什么我们需要URL编码:

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

如何在JS中实现URL编码:

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



encodeURIComponent():以URI的一部分作为参数并返回编码的URI字符串。

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无法正常运行。

因此(顾名思义)在要编码的URL的特定部分上使用:



encodeURIComponent

您要编码的整个URL上的encodeURI


#11 楼

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

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

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


#12 楼

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

在登录控制器中,我添加了以下这一行:
做到了这一点:

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


现在我没有任何问题了,它的工作原理就像是一种魅力。

#13 楼

编码URL字符串

    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


#14 楼

这是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>


#15 楼

您不应该直接使用encodeURIComponent()

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


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

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


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

MDN Web文档:encodeURIComponent()


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


使用MDN Web Docs函数。 ..

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


#16 楼

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

#17 楼

使用fixedEncodeURIComponent函数严格遵守RFC 3986:

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


#18 楼

性能

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

结论



encodeURI(B)似乎是最快的,但是不建议用于url -s

escape(A)是快速的跨浏览器解决方案
MDN建议的解决方案F是中等的快速
解决方案D最慢的是



详细信息

用于解决方案
A
B
C
D
E
F
我执行了两个测试


对于短网址-50个字符-您可以在此处运行

对于长网址-1M字符-您可以在此处运行它





 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的示例结果



#19 楼

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

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

#20 楼

我总是使用它来编码URL的内容。这是完全安全的,因为即使不需要编码,它也会对每个字符进行编码。
 function urlEncode(text) {
    encoded = '';
    for (let char of text) {
        encoded += '%' + char.charCodeAt(0).toString(16);
    }
    return encoded;
}