用JavaScript编码URL?

2020/09/14 16:31 · javascript ·  · 0评论

如何使用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(str)encodeURI(str)

在您的情况下,这应该可以工作:

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

您有三种选择:

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

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

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

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

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

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

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

最好的答案是使用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}`;

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

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

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

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

encodeURI()

encodeURIComponent()

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

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

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

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

我遇到了一个艰难的时期,提出了使用encodeURI()的理由-我会将其留给聪明的人。

优雅的方式

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

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

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

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

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

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

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

什么是网址编码:

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

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

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

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

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

什么都没有为我工作。我所看到的只是登录页面的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;
            }
        }
    });
});

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

编码URL字符串

    var url = $ location )。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

这里有一个现场演示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>

您不应该encodeURIComponent()直接使用

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

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

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

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

MDN Web文档:encodeURIComponent()

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

使用MDN网络文档功能...

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(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

使用fixedEncodeURIComponent功能严格遵守RFC 3986

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

性能

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

结论

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

在此处输入图片说明

细节

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

  • 短网址-50个字符-您可以在此处运行
  • 长网址-1M字符-您可以在此处运行

Chrome的结果范例

在此处输入图片说明

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

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

本文地址:http://javascript.askforanswer.com/yongjavascriptbianmaurl.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!