2692

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

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

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

4

21 回答 21

3016

查看内置函数encodeURIComponent(str)encodeURI(str)
在您的情况下,这应该有效:

var myOtherUrl = 
       "http://example.com/index.html?url=" + encodeURIComponent(myUrl);
于 2008-12-02T02:43:57.100 回答
1617

你有三个选择:

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

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

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

但在你的情况下,如果你想将一个URL传递给其他页面的GET参数,你应该使用escapeor encodeURIComponent,而不是encodeURI

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

于 2008-12-02T02:49:54.610 回答
195

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

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

于 2011-05-29T23:54:43.973 回答
88

最好的答案是使用查询字符串中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}`;
于 2012-12-15T08:47:32.280 回答
43

我建议使用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
于 2013-05-13T03:32:25.463 回答
15

现代解决方案 (2021)

由于编写了其他答案,因此引入了URLSearchParams API。它可以这样使用:

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

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

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

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

这里这里也提到了这个解决方案。

于 2019-11-15T14:30:50.973 回答
14

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', '+');
}
于 2015-10-01T08:03:26.453 回答
12

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

encodeURI()

encodeURIComponent()

两者都存在的原因是,第一个保留了 URL,可能会留下太多未转义的内容,而第二个则对所需的所有内容进行编码。

首先,您可以将新转义的 URL 复制到地址栏中(例如),它会起作用。但是,未转义的 '&' 会干扰字段分隔符,'=' 会干扰字段名称和值,并且 '+' 看起来像空格。但是对于简单的数据,当您想要保留您正在转义的 URL 特性时,这是可行的。

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

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

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

于 2017-01-26T21:31:43.957 回答
6

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

function fixedEncodeURIComponent(str){
     return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
}
于 2013-05-14T06:48:44.160 回答
6

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

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

encodeURI("abc%20xyz 123")            //   wrong: "abc%2520xyz%20123"
encodeURI(decodeURI("abc%20xyz 123")) // correct: "abc%20xyz%20123"
于 2017-01-05T18:49:48.467 回答
6

什么是 URL 编码:

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

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

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

为什么我们需要 URL 编码:

某些字符在 URL 字符串中具有特殊值。例如,? 字符表示查询字符串的开始。为了在网络上成功定位资源,必须区分字符是作为字符串的一部分还是作为 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 上。
于 2018-09-23T08:35:26.780 回答
5

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

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

子分隔符=“!” /“$”/“&”/“'”/“(”/“)”/“*”/“+”/“”/“;” /“=”

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

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

MDN 网络文档:encodeURIComponent()

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

使用 MDN Web Docs 功能...

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
于 2020-05-16T20:49:32.173 回答
4

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

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
console.log(myOtherUrl.searchParams.get('url'));
// Outputs: http://example.com/index.html?param=1&anotherParam=2

或者..

const params = new URLSearchParams(myOtherUrl.search);

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

这样的事情保证不会失败。

于 2021-07-01T13:11:12.947 回答
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;
            }
        }
    });
});

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

于 2012-06-22T03:28:01.250 回答
3

编码 URL 字符串

    var url = $(location).attr('href'); //获取当前网址
    //或者
    var url = '文件夹/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
于 2015-09-10T06:41:37.530 回答
3

这是一个和JS 内置函数的LIVE DEMO :encodeURIComponent()decodeURIComponent()

<!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>
于 2019-02-09T10:26:42.870 回答
3

表现

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

结论

  • encodeURI(B) 似乎最快但不推荐用于 url-s
  • escape(A) 快速跨浏览器解决方案
  • MDN推荐的解决方案F是中快
  • 解决方案 D 最慢

在此处输入图像描述

细节

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

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

在此处输入图像描述

于 2020-06-12T08:40:32.597 回答
2

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

于 2016-09-27T15:59:49.347 回答
2

使用fixedEncodeURIComponent函数严格遵守RFC 3986

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
于 2019-10-05T20:48:17.267 回答
1
var myOtherUrl = 
   "http://example.com/index.html?url=" + encodeURIComponent(myUrl).replace(/%20/g,'+');

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

于 2020-08-18T22:57:12.750 回答
-1

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

function urlEncode(text) {
    let encoded = '';
    for (let char of text) {
        encoded += '%' + char.charCodeAt(0).toString(16);
    }
    return encoded;
}
于 2020-12-11T03:24:55.120 回答