9

リンクのような小さな URL を作成することに興味があります。私のアイデアは、投稿されたすべての長い URL の増分識別子を単純に保存し、この ID を PHP の次のように base 36 バリアントに変換することでした。

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

ここでの問題は、結果が推測可能である一方で、次の URL が何であるかを推測するのは難しくなければならず、それでも短い (小さい) ことです。例えば。atm 最後の tinyurl が a1 だった場合、次は a2 になります。これは私にとって悪いことです。

では、結果として得られる小さな URL が推測可能ではないが短いことを確認するにはどうすればよいでしょうか?

4

9 に答える 9

9

あなたが求めているのは、情報の削減 (データベース内のインデックスへの URL) と情報の人為的な増加 (シーケンスに穴を作成するため) のバランスです。

両方があなたにとってどれほど重要かを判断する必要があります。もう 1 つの問題は、連続する URL を推測可能にしたくないだけなのか、それとも、有効な URL を推測するが困難になるほど十分にランダムにしたいのかということです。

基本的に、N 個の有効な ID のうち n 個を宣言します。URL を短くするには N を小さくし、推測しにくい URL を生成するには n を小さくします。n と N を大きくして、短い URL が取得されるときにより多くの URL を生成します。

ID を割り当てるには、任意の種類のランダム ジェネレーターまたはハッシュ関数を使用して、これをターゲット範囲 N に制限します。衝突が検出された場合は、次のランダム値を選択します。一意の ID の数が n 個に達した場合は、ID セットの範囲 (n と N) を増やす必要があります。

于 2010-08-06T21:45:16.093 に答える
5

私は単にcrc32 urlになります

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

短所: 定数 8 文字の長い識別子

于 2010-08-06T21:44:59.590 に答える
4

これは非常に安価ですが、ユーザーがそれが起こっていることを知らない場合、推測することはできませんが、実際の ID の前後に 2 つまたは 3 つの乱数/文字を追加します。

9d2a1me3 を見たとしても、dm2a2dq2 がシリーズの次だとは思いません。

于 2010-08-06T21:45:06.540 に答える
3

$id を何らかの値で Xor してみてください。たとえば$id ^ 46418、元の ID に戻すには、同じ Xor をもう一度実行するだけです$mungedId ^ 46418。これを base_convert と一緒にスタックし、おそらく結果の文字列でいくつかの文字を交換すると、URL を推測するのが非常に難しくなります。

于 2010-08-06T21:45:06.867 に答える
2

もう 1 つの方法は、URL の最大文字数を設定することです (たとえば、nです)。次に、順列番号となる 1 から n! の間の乱数を選択できます。

どの新しい URL で、ID をインクリメントし、順列番号を使用して、使用される実際の ID を関連付けます。最後に、URL を base 32 (または何でも) エンコードします。これは完全にランダムで、完全に可逆的です。

于 2010-08-06T22:18:39.460 に答える
1

単射関数が必要な場合は、任意の形式の暗号化を使用できます。例えば:

<?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"

逆にするには:

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

これは、基数 32 の数値を提供しません。各バイトが base 16 に変換された暗号化されたデータが得られます (つまり、変換はグローバルです)。本当に必要な場合は、これを基数 10 に簡単に変換してから、大きな整数をサポートするライブラリを使用して基数 32 に変換できます。

于 2010-08-06T21:55:32.937 に答える
0

事前に 4 文字のコード (考えられるすべての組み合わせ) を事前に定義してから、そのリストをランダム化し、このランダムな順序でデータ テーブルに格納できます。新しい値が必要な場合は、一番上にある最初の値を取得して、リストから削除します。これは高速で、オンザフライの計算ではなく、エンド ユーザーに疑似ランダム性を保証します。

于 2010-08-06T21:50:35.380 に答える
-1

私は最終的に識別子のmd5合計を作成し、その最初の4つの英数字を使用し、これが重複している場合は、重複しなくなるまで長さを増やします。

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

それが私をこの戦略に導いたので、reletの答えを受け入れました。

于 2010-08-06T23:43:48.493 に答える