2901

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

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

我假设您需要对我的URL第二行的变量?

5

22答案22

重置为默认值
3204

查看内置功能encodeURI组件(str)encodeURI(str).
在您的情况下,这应该有效:

var myOtherUrl="http://example.com/index.html?url=“+encodeURI组件(myUrl);
13
1693

您有三个选项:

  • 转义()将不编码:@*/+

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

  • 编码URI组件()将不编码:~!*()'

但就你而言,如果你想通过统一资源定位地址GET(获取)其他页面的参数,您应该使用逃跑encodeURI组件,但不是编码URI.

请参阅堆栈溢出问题最佳实践:escape或encodeURI/encodeURIComponent供进一步讨论。

10
  • 87
    转义使用的字符编码是可变的。坚持使用使用UTF-8的encodeURI和encodeURIComponent。 评论 2008年12月2日4:55
  • 8
    小心。该转义将非ASCII字符转换为其Unicode转义序列,如%uxxx公司.
    – 翼龙
    评论 2010年3月5日20:10
  • 4
    我正在使用encodeURIComponent,注意到它不会对管道字符进行编码| 评论 2011年1月30日5:05
  • 15
    @凯夫西特勒-为什么要这样做?管道在URI中没有语义重要性。
    – 刻痕
    评论 2011年1月31日11:36
  • 4
    @GiovanniP:允许输入德语、法语、日语、汉语、阿拉伯语字符,并通过GET或POST传递这些参数的人。
    – 
    评论 2013年9月4日14:43
205

坚持编码URI组件().功能编码URI()不用费心编码URL中具有语义重要性的许多字符(例如“#”、“?”和“&”)。擒纵机构()已弃用,并且不需要编码“+”字符,这将被解释为服务器上的编码空格(正如这里其他人指出的,没有正确地对非ASCII字符进行URL编码)。

有一个漂亮的解释两者之间的差异编码URI()编码URI组件()其他地方。如果您想对某些内容进行编码,以便可以将其安全地包括在URI的组件中(例如作为查询字符串参数),您需要使用编码URI组件().

0
105

最好的答案是使用encodeURI组件在查询字符串中(没有其他地方)。

然而,我发现许多较旧的API都想用“+”替换“”,因此我不得不使用以下内容:

const value=encodeURIComponent(value).replaceAll(“%20”,“+”);常量url='http://example.com?lang=en&key='+值

逃跑在不同的浏览器中实现方式不同编码URI不会对许多字符进行编码(例如#和even/)——它是为了在完整的URI/URL上使用而不破坏它——这既不太有用也不太安全。

正如@Jochem在下面指出的,您可能想使用编码URI组件()在(每个)文件夹名称上,但无论出于何种原因,这些API似乎并不需要+文件夹中的名称太普通了encodeURI组件效果很好。

例子:

const escapedValue=encodeURIComponent(value).replaceAll(“%20”,“+”);const escapedFolder=encodeURI组件(“我的文件夹”);//无需更换常量url=`http://example.com/${escapedFolder}/?myKey=${escapedValue}`;
8
  • 26
    请注意,您只应在第一个问号(URL的“查询”部分)后面用+符号替换%20。假设我想浏览到http://somedomain/this网址dir有空格/info.php?a=也有空格。应转换为:http://somedomain/this%20dir%20has%spaces/info.php?a=this%20has%20also%20spaces但许多实现都允许将查询字符串中的“%20”替换为“+”。然而,您不能在URL的路径部分将“%20”替换为“+”,这将导致“未找到”错误,除非您的目录具有+而不是空格。 评论 2013年1月20日1:08
  • @Jochem Kuijpers肯定不会把“+”放在目录中。我只会将此应用于查询参数值本身(或键(如果需要)),而不是整个URL,甚至整个查询字符串。
    – 泰勒
    评论 2013年7月19日22:16
  • 我将替换值而不是编码结果 评论 2014年6月2日18:11
  • 1
    @njzk2不幸encodeURI组件('+')会给你%2B型,所以您必须使用两个正则表达式。。。我想这就是为什么这样做的原因,因为“+”是“”最终的编码不同。
    – 泰勒
    评论 2014年6月2日18:17
  • 1
    不错,尽管我们需要使用.replaceAll(“%20”,“+”)来替换所有空格,而不仅仅是第一个空格
    – 尖晶石
    评论 1月10日10:07
44

我建议使用qs-npm包:

qs.stringify({a:“1=2”,b:“测试1”});//获得a=1%3D2&b=测试+1

它更容易与JavaScript对象一起使用,并为所有参数提供了正确的URL编码。

如果您使用jQuery,我会选择$.param(美元)方法。它通过URL对对象进行编码,将字段映射到值,这比对每个值调用转义方法更容易读取。

$.param({a:“1=2”,b:“Test 1”})//获取a=1%3D2&b=Test+1
41

现代解决方案(2021)

由于其他答案都写出来了URL搜索参数API已经引入。可以这样使用:

const queryParams={param1:“value1”,param2:“value2”}const queryString=新URLSearchParams(queryParams).toString()//'param1=value1&param2=value2'

它还对非URL字符进行编码。

对于您的具体示例,您可以这样使用:

const myUrl=“http://example.com/index.html?param=1&anotherParam=2";const myOtherUrl=新URL(“http://example.com/index.html");myOtherUrl.search=新URLSearchParams({url:myUrl});控制台.log(myOtherUrl.toString());

还提到了此解决方案在这里在这里.

1
  • 引起我问题的微妙部分(将空格编码为%20而不是+)通过使用解决了.toString()在URLSearchParams上 评论 1月24日17:32
17

我认为现在到2022年,为了真正安全,您应该始终考虑使用URL()接口。它能帮你完成大部分工作。所以在你的代码中,

const baseURL='http://example.com/index.html';const myUrl=新URL(baseURL);myUrl.searchParams.append('param','1');myUrl.searchParams.append('otherParam','2');const myOtherUrl=新URL(baseURL);myOtherUrl.searchParams.append('url',myUrl.href);console.log(myUrl.href);//输出:http://example.com/index.html?param=1&anotherParam=2console.log(myOtherUrl.href);//输出:http://example.com/index.html?url=http%3A%2F%2Example.com%2Index.html%3Fparam%3D1%26anotherParam%3D2控制台.log(myOtherUrl.searchParams.get('url'));//输出:http://example.com/index.html?param=1&anotherParam=2

或者。。。

const-params=新URLSearchParams(myOtherUrl.search);console.log(params.get('url'));//输出:http://example.com/index.html?param=1-anotherParam=2

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

15

encodeURIComponent()是一种方法。

var myOtherUrl=“http://example.com/index.html?url=“+encodeURI组件(myUrl);

但是您应该记住,与PHP版本有一些小的差异urlencode()正如@CMS所提到的,它不会对每个字符进行编码。各位http://phpjs.org/functions/urlencode/使JavaScript等效于phpencode():

函数urlencode(str){str=(str+'').toString();//在PHP的未来版本中应该允许不转义颚化符(如下所示),但如果您想反映当前的//PHP行为,您需要在下面添加“.replace(/~/g,'%7E');”。返回encodeURIComponent(str).replace(“!”,“%21”).replace(“\”,“%27”).replace(“(”,“%28”).replace(')',“%29”).replace(“*”,“%2A”).replace(“%20”,“+”);}
12

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

编码URI()

编码URI组件()

两者都存在的原因是,第一种方法保留了URL,而第二种方法则对所有需要的内容进行编码。

使用第一种方法,您可以将新转义的URL复制到地址栏中(例如),这样就可以工作了。然而,未转义的“&”会干扰字段分隔符,“=”会干扰域名称和值,“+”看起来像空格。但对于简单的数据,当您想保留正在转义的内容的URL性质时,这是可行的。

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

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

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

10

什么是URL编码:

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

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

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

为什么需要URL编码:

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

如何在JavaScript中实现URL编码:

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

  1. 编码URI组件():将URI的组件作为参数并返回编码的URI字符串。
  2. 编码URI():将URI作为参数并返回编码的URI字符串。

示例和注意事项:

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

//对于整个URI,不要使用encodeURIComponent,它将转换///字符和URL无法正常工作console.log(encodeURIComponent(“http://www.random.com/specials&char.html(网址:http://www.random.com/specials&char.html)"));//而是对整个URL使用encodeURIconsole.log(encodeURI(“http://www.random.com/specials&char.html"));

我们可以观察是否将整个URL放在encodeURI组件正斜杠(/)也被转换为特殊字符。这将导致URL无法正常工作。

因此(顾名思义)使用:

  1. encodeURI组件在您想要编码的URL的特定部分。
  2. 编码URI在您要编码的整个URL上。
7

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

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

encodeURI(“abc%20xyz 123”)//错误:“abc/2520xyz%20123”encodeURI(decodeURI(“abc%20xyz 123”)//正确:“abc%20xyz%20123”
6

你不应该使用编码URI组件()直接。

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

子装饰=“!”/“$”/“&”/“'”/“(”/“)”/ "*" / "+" / "," / ";" / "="

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

RFC3986中URI定义中的这些保留字符不是由转义的编码URI组件().

MDN Web文档:encodeURIComponent()

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

使用MDN Web文档功能。。。

函数fixedEncodeURIComponent(str){return encodeURIComponent(str).replace(/[!'()*]/g,函数(c){返回“%”+c.charCodeAt(0).toString(16);});}
6

我用普通JavaScript做过类似的事情:

函数fixedEncodeURIComponent(str){return encodeURIComponent(str).replace(/[!'()]/g,转义).replace(/\*/g,“%2A”);}
1
  • 你能解释一下你的答案吗?例如,为什么是神奇的十六进制数“2A”?(即“*”(星号)ASCII格式。)请回复编辑(更改)您的答案,不在评论中(********************没有********************“编辑:”、“更新:”或类似内容-答案应该像今天写的一样出现)。 评论 2022年12月8日0:39
5

性能

今天(2020.06.12),我在macOS v10.13.6(High Sierra)在浏览器Chrome 83.0、Safari 13.1和Firefox 77.0上运行。此结果对于大规模URL编码非常有用。

结论

  • 编码URI(B) 似乎是最快的,但不是建议用于URL
  • 逃跑(A) 是一种快速的跨浏览器解决方案
  • 建议的解决方案FMDN公司中等速度
  • 解决方案D最慢

在此处输入图像描述

细节

对于解决方案A类 B类 C类 D类 E类 F类我做了两次测试

函数A(url){返回转义(url);}函数B(url){返回encodeURI(url);}函数C(url){return encodeURIComponent(url);}函数D(url){return new URLSearchParams({url}).toString();}函数E(url){return encodeURIComponent(url).replace(/[!'()]/g,escape).replay(/\*/g,“%2A”);}函数F(url){return encodeURIComponent(url).replace(/[!'()*]/g,函数(c){返回“%”+c.charCodeAt(0).toString(16);});}// ----------//测试// ----------var myUrl=“http://example.com/index.html?param=1&anotherParam=2";【A、B、C、D、E、F】.forEach(f=>控制台.log(`${f.name}?url=${f(myUrl).replace(/^url=/,')}`));
此片段仅显示所选解决方案的代码

Chrome的示例结果

在此处输入图像描述

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

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

回应。Headers[“land”]=“login”;

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

$(函数(){var$document=$(文档);$document.ajaxSuccess(函数(e,响应,请求){var land=响应.getResponseHeader('land');var redrUrl='/login?ReturnUrl=“+encodeURIComponent(window.location);if(陆地){if(land.toString()===“登录”){window.location=刷新URL;}}});});

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

使用固定编码URI组件严格遵守的功能副本请求3986:

函数fixedEncodeURIComponent(str){return encodeURIComponent(str).replace(/[!'()*]/g,函数(c){返回“%”+c.charCodeAt(0).toString(16);});}

这里有一个现场演示属于encodeURI组件()解码URI组件()JavaScript内置函数:

<!DOCTYPE html><html><头部><样式>文本区域{宽度:30%;高度:100px;}</style><脚本>//将字符串编码为Base64函数编码(){var txt=文档.getElementById(“txt1”).value;var结果=btoa(txt);document.getElementById(“txt2”).value=结果;}//将Base64解码回原始字符串函数decode(){var txt=文档.getElementById(“txt3”).value;var结果=atob(txt);document.getElementById(“txt4”).value=结果;}</script></头><body><div><textarea id=“txt1”>要解码的一些文本</text区域></div><div><input type=“button”id=“btnencode”value=“Encode”onClick=“Encode()”/></div><div><textarea id=“txt2”></text区域></div><br/><div>U29tZSB0ZXh0IHRvIGRlY29kZQ==</text区域></div><div><input type=“button”id=“btndecode”value=“解码”onClick=“Decode()”/></div><div><textarea id=“txt4”></text区域></div></body></html>

编码URL字符串

var url=$(位置).attr('href');//获取当前URL//或者var url='文件夹/index.html?param=#23dd&noob=yes';//或指定一个var encodedUrl=编码URI组件(url);console.log(encodedUrl);//输出文件夹%2Index.html%3Fparam%3D%2323dd%26noob%3Yes

有关更多信息,请访问,jQuery编码/解码URL字符串.

2

您可以使用欧洲标准协会库并使用以下函数对URL进行编码。该函数确保在对其余文本内容进行编码时,“/”不会因编码而丢失:

函数encodeUrl(url){字符串arr[]=url.split(“/”);字符串编码Url=“”;for(int i=0;i<arr.length;i++){encodedUrl=编码Url+ESAPI.encoder().encodeForHTML(ESAPI.编码器().engodeForURL(arr[i]));如果(i<arr.length-1)encodedUrl=encodedUrl+“/”;}返回url;}
1
  • 原始URL重定向。上面有预期的内容吗? 评论 2022年11月27日22:16
1

不要忘记使用/g标志替换所有编码的“”

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

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

函数urlEncode(文本){let编码=“”;for(让文本字符){编码+=“%”+char.charCodeAt(0).toString(16);}返回编码;}
1
  • 尽管这不是标准的(不会在get请求中使用),但它对编码任何字符都很有用(例如,用于网络攻击),但对于只有1个十六进制长的字符,需要用0填充。它也应该大写。 评论 2022年11月27日2:31
0

let name=`bbb`;params=`name=${name}`;var myOtherUrl=`http://example.com/index.html?url=${encodeURIComponent(params)}`;控制台.log(myOtherUrl);

现在在ES6中使用反勾号对url进行编码

试试这个-https://bbbootstrap.com/code/encode-url-javascript-26885283

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.