2010-08-06 5 views
6

Ich bin daran interessiert, kleine URL-ähnliche Links zu erstellen. Meine Idee war, einfach zu speichern, eine Inkrementierung Kennung für jede lange URL geschrieben und dann diese ID zu konvertieren, um es der Basis 36-Variante, wie die folgend in PHP:Wie kann man eine "kleine URL" basierend auf einer ID erzeugen?

$tinyurl = base_convert($id, 10, 36) 

Das Problem hierbei ist, dass das Ergebnis zu erraten ist, während es muss schwer zu erraten sein, was die nächste URL sein wird, während sie immer noch kurz (winzig) ist. Z.B. atm, wenn mein letzter tinyurl a1 war, wird der nächste a2 sein. Das ist eine schlechte Sache für mich.

Also, wie würde ich sicherstellen, dass die daraus resultierende winzige URL nicht so wahrscheinlich, aber immer noch kurz ist?

Antwort

9

Was Sie verlangen, ist ein Gleichgewicht zwischen der Reduzierung von Informationen (URLs zu ihren Indizes in Ihrer Datenbank) und künstlicher Zunahme von Informationen (um Löcher in Ihrer Sequenz zu erzeugen).

Sie müssen entscheiden, wie wichtig beides für Sie ist. Eine andere Frage ist, ob Sie einfach nicht möchten, dass sequenzielle URLs erraten werden oder dass sie ausreichend zufällig sind, um das Erraten einer beliebigen gültigen URL zu erschweren.

Grundsätzlich möchten Sie n aus N gültigen IDs deklarieren. Wählen Sie N kleiner, um die URLs kürzer zu machen, und n, um URLs zu generieren, die schwer zu erraten sind. Machen Sie n und N größer, um mehr URLs zu erzeugen, wenn die kürzeren genommen werden.

Um die IDs zuzuweisen, können Sie beliebige Zufallsgeneratoren oder Hashfunktionen verwenden und diese auf Ihren Zielbereich N kappen. Wenn Sie eine Kollision feststellen, wählen Sie den nächsten zufälligen Wert. Wenn Sie eine Anzahl von n eindeutigen IDs erreicht haben, müssen Sie den Bereich Ihres ID-Satzes (n und N) vergrößern.

+0

In Bezug auf Ihren letzten Absatz. Ich denke, er möchte einen Wert, den er umkehren kann, d. H. Er möchte eine injektive Funktion haben. – Artefacto

+1

Nein, er möchte wirklich eine unkalkulierbare Funktion haben. ;) Da er die URLs trotzdem in einer Datenbank speichern muss, kann er die Zufallszahl als Index verwenden. Umkehrung erreicht. – relet

+0

Stimmt, muss nicht injektiv sein. – Tom

5

Ich würde einfach crc32 url

$url = 'http://www.google.com'; 
$tinyurl = hash('crc32', $url); // db85f073 

Nachteile: Konstante 8 Zeichen lang Kennung

+0

Ich mag diese Idee, aber der 8-stelligen Code ist eine Art ein Problem - mit URL Shortener in diesen Tagen, jeder Charakter zählt, und 8 ist ein wenig hoch. –

4

Das ist wirklich billig, aber wenn der Benutzer nicht weiß, dass es passiert, es ist dann nicht als erratbar, aber Präfix und postfix die tatsächliche ID mit 2 oder 3 Zufallszahlen/Buchstaben.

Wenn ich 9d2a1me3 sah, würde ich nicht vermuten, dass dm2a2dq2 der nächste in der Reihe war.

2

Versuchen Sie Xor'ing die $ ID mit einem Wert, z. $id^46418 - und um zurück zu Ihrer ursprünglichen ID zu konvertieren, führen Sie einfach dasselbe Xor erneut aus, d. H. $mungedId^46418. Stapeln Sie das zusammen mit Ihrem base_convert und vielleicht ein paar Zeichen in der resultierenden Zeichenfolge und es wird ziemlich schwierig, eine URL zu erraten.

+0

Dies ist sehr leicht zu brechen. – Artefacto

+0

Für einen etwas entschlossenen Hacker sicher - für Joe Public nicht so sehr. –

0

Sie können die 4-stelligen Codes im Voraus (alle möglichen Kombinationen) vordefinieren, dann diese Liste zufällig anordnen und in dieser zufälligen Reihenfolge in einer Datentabelle speichern. Wenn Sie einen neuen Wert wünschen, nehmen Sie einfach den ersten von oben und entfernen Sie ihn aus der Liste. Es ist schnell, keine fliegende Berechnung und garantiert dem Endbenutzer Pseudozufälligkeit.

+0

Allerdings skaliert es nicht. – relet

+1

Ich sollte darauf hinweisen, dass dies genau das ist, was ich für einen URL-Shortener getan habe, und es ist ein bisschen mühsam, loszulegen. Es gibt eine Menge möglicher Kombinationen, was bedeutet, dass Sie mit einer riesigen Datenbankdatei für ein so einfaches Konzept beginnen. –

+0

@relet Worauf genau beziehen Sie sich? Die Tatsache, dass es eine begrenzte Anzahl gibt, die nicht erhöht werden kann? Wenn das der Fall ist, berechnen Sie alle 5-stelligen Codes und fügen Sie diese in Ihre Queue-Tabelle ein. –

1

Wenn Sie eine injektive Funktion wünschen, können Sie jede Form der Verschlüsselung verwenden.Zum Beispiel:

<?php 
$key = "my secret"; 
$enc = mcrypt_ecb (MCRYPT_3DES, $key, "42", MCRYPT_ENCRYPT); 
$f = unpack("H*", $enc); 
$value = reset($f); 
var_dump($value); //string(16) "1399e6a37a6e9870" 

Zum Umkehren:

$rf = pack("H*", $value); 
$dec = rtrim(mcrypt_ecb (MCRYPT_3DES, $key, $rf, MCRYPT_DECRYPT), "\x00"); 
var_dump($dec); //string(2) "42" 

Dies wird nicht eine Zahl mit der Basis geben 32; Sie erhalten die verschlüsselten Daten, wobei jedes Byte in die Basis 16 konvertiert wird (d. h. die Konvertierung ist global). Wenn Sie wirklich brauchen, können Sie dies trivialerweise in Basis 10 und dann in Basis 32 mit jeder Bibliothek konvertieren, die große Ganzzahlen unterstützt.

+0

Beachten Sie, dass die resultierende URL kurz sein muss (1399e6a37a6e9870 ist zu lang). – Tom

+0

@Tom Nun, er könnte es in Base 64 oder so konvertieren und (glaube ich) 11 Zeichen bekommen. Oder verwenden Sie – Artefacto

2

Eine andere Möglichkeit wäre, die maximale Anzahl von Zeichen für die URL zu setzen (sagen wir mal n). Sie könnten dann eine zufällige Zahl zwischen 1 und n! Wählen, was Ihre Permutationsnummer wäre.

Auf welcher neuen URL würden Sie die ID erhöhen und die Permutationsnummer verwenden, um die tatsächliche ID zuzuordnen, die verwendet würde. Schließlich würden Sie 32 (oder was auch immer) codieren Ihre URL. Dies wäre vollkommen zufällig und vollkommen reversibel.

+0

Duplikate-IDs sind auf diese Weise möglich, Sie müssten dies also überprüfen und bei einer Wiederholung erneut inkrementieren. – Tom

+0

@Tom Nein, sie würden nicht ... – Artefacto

-1

Ich habe am Ende eine MD5-Summe des Bezeichners erstellt, verwende die ersten 4 alphanumerischen Zeichen davon und wenn es ein Duplikat ist, inkrementiere einfach die Länge, bis es kein Duplikat mehr ist.

function idToTinyurl($id) { 
    $md5 = md5($id); 
    for ($i = 4; $i < strlen($md5); $i++) { 
     $possibleTinyurl = substr($md5, 0, $i); 
     $res = mysql_query("SELECT id FROM tabke WHERE tinyurl='".$possibleTinyurl."' LIMIT 1"); 
     if (mysql_num_rows($res) == 0) return $possibleTinyurl; 
    } 
    return $md5; 
} 

Akzeptierte Relet's Antwort, da es mich zu dieser Strategie geführt hat.

0

Hashids ist eine Open-Source-Bibliothek, die kurze, eindeutige, nicht sequentielle, YouTube-ähnliche IDs aus einer oder mehreren Zahlen generiert. Sie können es als einen Algorithmus zur Verschleierung von Zahlen vorstellen.

Es wandelt Zahlen wie 347 in Strings wie "yr8" oder Array wie [27, 986] in "3kTMd" um. Sie können diese IDs auch zurückdecodieren. Dies ist nützlich, um mehrere Parameter zu einem einzigen zu bündeln oder einfach als kurze UIDs zu verwenden.

es verwenden, wenn Sie nicht wollen, zu Ihre Datenbank ids an den Benutzer aus.

Es erlaubt benutzerdefinierte Alphabet sowie Salz, so IDs sind nur für Sie einzigartig.

Der inkrementelle Eingang wird nicht erkannt.

Es gibt keine Kollisionen, da die Methode auf einer Ganzzahl-Hex-Konvertierung basiert.

Es wurde mit der Absicht geschrieben, erstellte IDs an sichtbaren Stellen wie der URL zu platzieren. Daher vermeidet der Algorithmus das Generieren der häufigsten englischen Schimpfwörter.

Codebeispiel

$hashids = new Hashids(); 
$id = $hashids->encode(1, 2, 3); // o2fXhV 
$numbers = $hashids->decode($id); // [1, 2, 3] 
Verwandte Themen