URL in JavaScript verschlüsseln?

2469

Wie codieren Sie eine URL sicher mit JavaScript, sodass sie in eine GET-Zeichenfolge eingefügt werden kann?

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

Ich gehe davon aus, dass Sie die myUrlVariable in dieser zweiten Zeile codieren müssen ?

nickf
quelle
22
Schauen Sie sich encodeURI () und decodeURI () an .
Zack The Human
1
Sie können dieses Tool hier verwenden: phillihp.com/toolz/url-encode-decode
phillihp
2
encodeURIComponent ()
Andrew

Antworten:

2791

Überprüfen Sie die integrierten Funktionen encodeURIComponent (str) und encodeURI (str) .
In Ihrem Fall sollte dies funktionieren:

var myOtherUrl = 
       "http://example.com/index.html?url=" + encodeURIComponent(myUrl);
Buu Nguyen
quelle
12
Wie wäre es mit der Erklärung, die @cms gegeben hat? escapeist auch eine gültige Option.
Hitautodestruct
11
Laut @CMS encodeURIist die URL-Codierung nicht wirklich sicher.
Ifnot
13
@AnaelFavre weil es bedeutet , ist die gesamte URL zu kodieren, die Zeichen nicht erlauben, wie :, /, @usw. Diese zwei Verfahren sind nicht untereinander austauschbar verwendet werden, müssen Sie wissen , was Sie codieren , die richtige Methode zu verwenden.
Buu Nguyen
Wie in einer anderen Antwort auf dieser Seite erwähnt , beschreibt diese Seite den Grund für die Verwendung dieser Methode
Brad Parks
1521

Sie haben drei Möglichkeiten:

  • escape() wird nicht codieren: @*/+

  • encodeURI() wird nicht codieren: ~!@#$&*()=:/,;?+'

  • encodeURIComponent() wird nicht codieren: ~!*()'

Wenn Sie in Ihrem Fall eine URL an einen GETParameter einer anderen Seite übergeben möchten , sollten Sie escapeoder verwenden encodeURIComponent, aber nichtencodeURI .

Weitere Informationen finden Sie unter Best Practice für Stapelüberlauf: Escape oder encodeURI / encodeURIComponent .

CMS
quelle
76
Die mit Escape verwendete Zeichenkodierung ist variabel. Halten Sie sich an encodeURI und encodeURIComponent, die UTF-8 verwenden.
Erickson
6
Achtung. Dieses Escape konvertiert Nicht-ASCII-Zeichen in seine Unicode-Escape-Sequenzen, wie z %uxxx.
Opteronn
4
Ich verwende encodeURIComponent und stelle fest, dass keine Pipe-Zeichen | codiert werden
Kevzettler
15
@kevzettler - warum sollte es das tun? Die Pipes sind in einer URI nicht von semantischer Bedeutung.
Nickf
4
@GiovanniP: Personen, die deutsche, französische, japanische, chinesische, arabische Zeichen als Eingabe zulassen und diese Parameter über GET oder POST übergeben.
Tseng
180

Bleib bei encodeURIComponent(). Die Funktion encodeURI()macht sich nicht die Mühe, viele Zeichen zu codieren, die in URLs semantische Bedeutung haben (z. B. "#", "?" Und "&"). escape()ist veraltet und macht sich nicht die Mühe, "+" - Zeichen zu codieren, die als codierte Leerzeichen auf dem Server interpretiert werden (und, wie von anderen hier hervorgehoben, Nicht-ASCII-Zeichen nicht ordnungsgemäß per URL codieren).

Es gibt eine schöne Erklärung für den Unterschied zwischen encodeURI()undencodeURIComponent() anderswo. Wenn Sie etwas so codieren möchten, dass es sicher als Komponente eines URI enthalten sein kann (z. B. als Abfragezeichenfolgenparameter), möchten Sie es verwenden encodeURIComponent().

Mike Brennan
quelle
83

Die beste Antwort ist die Verwendung encodeURIComponentvon Werten in der Abfragezeichenfolge (und nirgendwo anders).

Ich finde jedoch, dass viele APIs "" durch "+" ersetzen möchten, daher musste ich Folgendes verwenden:

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

escapewird in verschiedenen Browsern unterschiedlich implementiert und encodeURIcodiert nicht viele Zeichen (wie # und sogar /) - es kann für eine vollständige URI / URL verwendet werden, ohne diese zu beschädigen - was nicht besonders hilfreich oder sicher ist.

Und wie @Jochem weiter unten ausführt, möchten Sie möglicherweise encodeURIComponent()einen (jeden) Ordnernamen verwenden, aber aus irgendeinem Grund scheinen diese APIs in Ordnernamen nicht zu wollen, +so dass einfach alt encodeURIComponentgroßartig funktioniert.

Beispiel:

const escapedValue = encodeURIComponent(value).replace('%20','+');
const escapedFolder = encodeURIComponent('My Folder'); // no replace
const url = `http://example.com/${escapedFolder}/?myKey=${escapedValue}`;
Ryan Taylor
quelle
22
Bitte beachten Sie, dass Sie% 20 erst nach dem ersten Fragezeichen (dem Abfrageteil der URL) durch + Symbole ersetzen sollten. Angenommen, ich möchte zu navigieren http://somedomain/this dir has spaces/info.php?a=this has also spaces. Es sollte konvertiert werden in: Bei http://somedomain/this%20dir%20has%spaces/info.php?a=this%20has%20also%20spacesvielen Implementierungen kann jedoch '% 20' im Querystring durch '+' ersetzt werden. Trotzdem können Sie '% 20' im Pfadabschnitt der URL nicht durch '+' ersetzen. Dies führt zu einem Fehler "Nicht gefunden", es sei denn, Sie haben ein Verzeichnis mit einem +anstelle eines Leerzeichens.
Jochem Kuijpers
@Jochem Kuijpers, definitiv würden Sie nicht "+" in ein Verzeichnis setzen. Ich würde dies nur auf die Abfrageparameterwerte selbst (oder Schlüssel, falls erforderlich) anwenden, nicht auf die gesamte URL oder sogar die gesamte Abfragezeichenfolge.
Ryan Taylor
Ich würde eher im Wert als im Ergebnis der Codierung
ersetzen
1
@ njzk2 encodeURIComponent('+')würde dir leider geben %2B, also müsstest du zwei reguläre Ausdrücke verwenden ... was vermutlich der Grund ist, warum dies funktioniert, weil '+' are '' am Ende anders codiert sind.
Ryan Taylor
Es gibt keinen Grund,% 20 in "+" zu übersetzen. Die gültige Escape-Sequenz für den ASCII-Speicher ist% 20, nicht "+", was in RFC 3986 ( tools.ietf.org/html/rfc3986 ) nicht erwähnt wird . "+" wurde in den 1990er Jahren verwendet; Es ist jetzt veraltet und wird nur aus früheren Gründen unterstützt. Benutze es nicht.
xhienne
40

Wenn Sie jQuery verwenden, würde ich mich für eine $.paramMethode entscheiden. Die URL codiert ein Objekt, das Felder Werten zuordnet. Dies ist einfacher zu lesen als das Aufrufen einer Escape-Methode für jeden Wert.

$.param({a:"1=2", b:"Test 1"}) // gets a=1%3D2&b=Test+1
Maksym Kozlenko
quelle
Ich halte dieses Beispiel für ausreichend. Wenn Sie weitere Informationen über $ .param auf api.jquery.com/jquery.param
Maksym Kozlenko
Fast jeder benutzt jQuery und ich fühle mich in der Tat wohler damit als mit encoreURIComponent
Cyril Duchon-Doris
12

encodeURIComponent () ist der richtige Weg.

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

ABER Sie sollten bedenken, dass es kleine Unterschiede zur PHP-Version gibt urlencode()und wie @CMS erwähnt, nicht jedes Zeichen codiert. Typen bei http://phpjs.org/functions/urlencode/ gemacht js äquivalent zu 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', '+');
}
Adam Fischer
quelle
10

Wie bereits erwähnt, haben Sie zwei Funktionen, um eine URL zu verschlüsseln:

encodeURI()

und

encodeURIComponent()

Der Grund dafür ist, dass der erste die URL beibehält und das Risiko besteht, dass zu viele Dinge nicht entkommen, während der zweite alles verschlüsselt, was benötigt wird.

Mit dem ersten könnten Sie die neu maskierte URL in die Adressleiste kopieren (zum Beispiel) und es würde funktionieren. Ihre nicht entkoppelten '&' würden jedoch Feldbegrenzer stören, die '=' würden Feldnamen und Werte stören und die '+' würden wie Leerzeichen aussehen. Bei einfachen Daten funktioniert dies jedoch, wenn Sie die URL-Natur Ihrer Escape-Daten beibehalten möchten.

Das zweite ist alles, was Sie tun müssen, um sicherzustellen, dass nichts in Ihrer Zeichenfolge mit einer URL interferiert. Es bleiben verschiedene unwichtige Zeichen unberührt, so dass die URL so störungsfrei wie möglich bleibt. Eine auf diese Weise codierte URL funktioniert nicht mehr als URL, ohne sie zu entfernen.

Wenn Sie sich also die Zeit nehmen können, möchten Sie immer encodeURIComponent () verwenden - bevor Sie Name / Wert-Paare hinzufügen, codieren Sie mit dieser Funktion sowohl den Namen als auch den Wert, bevor Sie ihn zur Abfragezeichenfolge hinzufügen.

Es fällt mir schwer, Gründe für die Verwendung von encodeURI () zu finden - das überlasse ich den klügeren Leuten.

Gerard ONeill
quelle
5

Ähnliches habe ich mit normalem Javascript versucht

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

Eleganter Weg

Meiner bescheidenen Meinung nach besteht die eleganteste Art, Abfrageparameter zu codieren, darin, ein Objekt mit Parametern wie zu erstellen

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

und codieren Sie es dann mit:

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

wie in dieser Antwort erwähnt: https://stackoverflow.com/a/53171438/7284582

Qback
quelle
4

Um eine doppelte Codierung zu verhindern, empfiehlt es sich, die URL vor der Codierung zu dekodieren (wenn Sie beispielsweise mit vom Benutzer eingegebenen URLs arbeiten, die möglicherweise bereits codiert sind).

Nehmen wir an, wir haben abc%20xyz 123als Eingabe (ein Leerzeichen ist bereits codiert):

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

Was ist URL-Codierung:

Eine URL sollte verschlüsselt werden, wenn sich in der URL Sonderzeichen befinden. Zum Beispiel:

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

In diesem Beispiel können wir beobachten, dass alle Zeichen außer der Zeichenfolge notEncodedmit% -Zeichen codiert sind. Die URL-Codierung wird auch als prozentuale Codierung bezeichnet, da alle Sonderzeichen mit einem% maskiert werden. Nach diesem% -Zeichen hat jedes Sonderzeichen einen eindeutigen Code

Warum brauchen wir eine URL-Codierung:

Bestimmte Zeichen haben einen speziellen Wert in einer URL-Zeichenfolge. Zum Beispiel die? Zeichen bezeichnet den Anfang einer Abfragezeichenfolge. Um eine Ressource im Web erfolgreich zu finden, muss unterschieden werden, wann ein Zeichen als Teil einer Zeichenfolge oder als Teil der URL-Struktur gedacht ist.

Wie können wir eine URL-Codierung in JS erreichen:

JS bietet eine Reihe von integrierten Dienstprogrammfunktionen, mit denen wir URLs einfach codieren können. Dies sind zwei praktische Optionen:

  1. encodeURIComponent(): Nimmt eine Komponente eines URI als Argument und gibt die codierte URI-Zeichenfolge zurück.
  2. encodeURI(): Nimmt einen URI als Argument und gibt die codierte URI-Zeichenfolge zurück.

Beispiel und Vorbehalte:

Beachten Sie, dass nicht die gesamte URL (einschließlich Schema, z. B. https: //) an übergeben wird encodeURIComponent(). Dies kann es tatsächlich in eine nicht funktionierende URL umwandeln. Zum Beispiel:

// 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"));

Wir können beobachten, dass wir die gesamte URL so encodeURIComponenteingeben, dass die Schrägstriche (/) auch in Sonderzeichen umgewandelt werden. Dies führt dazu, dass die URL nicht mehr richtig funktioniert.

Verwenden Sie daher (wie der Name schon sagt):

  1. encodeURIComponent auf einem bestimmten Teil einer URL, die Sie codieren möchten.
  2. encodeURI auf eine ganze URL, die Sie codieren möchten.
Willem van der Veen
quelle
3

Bei mir hat nichts funktioniert. Alles, was ich sah, war der HTML-Code der Anmeldeseite, der mit Code 200 auf die Clientseite zurückkehrte. (Zuerst 302, aber dieselbe Ajax-Anfrage, die die Anmeldeseite in eine andere Ajax-Anfrage lädt, die eher eine Weiterleitung als eine einfache Ebene sein sollte Text der Anmeldeseite).

Im Login-Controller habe ich folgende Zeile hinzugefügt:

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

Und im globalen Ajax-Handler habe ich Folgendes getan:

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

Jetzt habe ich kein Problem und es funktioniert wie ein Zauber.

Asif Ashraf
quelle
2

URL-Zeichenfolge codieren

    var url = $ ( Speicherort ). attr ( 'href' ); // aktuelle URL abrufen // ODER var url = 'folder / index.html? param = # 23dd & noob = yes' ; // oder geben Sie eine an 
    
      

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
Sangeet Shah
quelle
2

Hier ist eine LIVE DEMO von encodeURIComponent()und decodeURIComponent()JS integrierte Funktionen:

<!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>
Jonathana
quelle
1

Sie können die esapi-Bibliothek verwenden und Ihre URL mit der folgenden Funktion codieren. Die Funktion stellt sicher, dass '/' nicht durch Codierung verloren geht, während der Rest des Textinhalts codiert wird:

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

Mohith Maratt
quelle
1

Verwenden Sie die fixedEncodeURIComponentFunktion, um RFC 3986 strikt einzuhalten :

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

Sie sollten nicht encodeURIComponent()direkt verwenden.

Schauen Sie sich RFC3986 an: URI (Uniform Resource Identifier): Generische Syntax

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

Der Zweck reservierter Zeichen besteht darin, eine Reihe von Begrenzungszeichen bereitzustellen, die von anderen Daten innerhalb eines URI unterscheidbar sind.

Diese reservierten Zeichen aus der URI-Definition in RFC3986 werden NICHT maskiert encodeURIComponent().

MDN-Webdokumente: encodeURIComponent ()

Um die Einhaltung von RFC 3986 (das reserviert !, ', (,) Und *) strenger zu gestalten, kann Folgendes sicher verwendet werden, obwohl diese Zeichen keine formalisierten URI-Begrenzungsverwendungen haben:

Verwenden Sie die MDN Web Docs-Funktion ...

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