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

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

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


当前回答

不应直接使用encodeURIComponent()。

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

sub-delims=“!”/“$”/“&”/“'”/“(”/“)”/ "*" / "+" / "," / ";" / "="保留字符的目的是提供一组可与URI中的其他数据区分的分隔字符。

这些来自RFC3986中URI定义的保留字符不会被encodeURIComponent()转义。

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

其他回答

最好的答案是对查询字符串中的值使用encodeURIComponent(而不是其他)。

然而,我发现许多API都想用“+”替换“”,所以我不得不使用以下方法:

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

escape在不同浏览器中的实现方式不同,encodeURI不编码许多字符(如#和甚至/)——它可以在完整的URI/URL上使用,而不会破坏它——这并不是非常有用或安全的。

正如@Jochem在下面指出的,您可能希望在(每个)文件夹名称上使用encodeURIComponent(),但无论出于什么原因,这些API似乎不希望在文件夹名称中使用+,所以普通的encodeURIComponents非常有用。

例子:

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

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

encodeURI()

and

encodeURIComponent()

两者都存在的原因是,第一种方法保留了URL,但有可能留下太多未被屏蔽的内容,而第二种方法对所有需要的内容进行编码。

使用第一个,您可以将新转义的URL复制到地址栏中(例如),这样就可以了。然而,未转义的‘&’会干扰字段分隔符,‘=’会干扰域名和值,‘+’看起来像空格。但对于简单的数据,当您希望保留要转义的内容的URL性质时,这是有效的。

第二个是您需要做的一切,以确保字符串中没有任何内容干扰URL。它保留了各种不重要的字符,使URL尽可能保持可读性而不受干扰。以这种方式编码的URL将不再作为URL工作,而不会取消其标题。

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

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

编码URL字符串

var url = $(location).attr('href'); // Get the 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

有关详细信息,请转到jQuery编码/解码URL字符串。

没有什么对我有用。我看到的只是登录页面的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;
            }
        }
    });
});

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

这里是encodeURIComponent()和decodeURIComponent()JavaScript内置函数的现场演示:

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