2010-09-27 13 views
6

Mi sto scrivendo uno script che fondamentalmente mi consente di inviare un URL e due dimensioni integer nella query quer di una singola richiesta di ottenere. Sto usando base64 per codificarlo, ma è piuttosto dannatamente lungo e temo che l'URL possa diventare troppo grande.PHP: codifica più breve/oscurata per un URL incorporato in un altro URL?

Qualcuno conosce un metodo alternativo e più breve per farlo? Deve essere decodificabile quando viene ricevuto in una richiesta get, quindi md5/sha1 non è possibile.

Grazie per il vostro tempo.


Edit: Scusa - mi avrebbe dovuto spiegare meglio: Ok, sul nostro sito abbiamo visualizzare gli screenshot di siti web che vengono pubblicati per la revisione. Abbiamo il nostro server thumbnail/screenshot. Praticamente avrò il tag immagine contenere una stringa codificata che memorizza l'URL per fare uno screenshot e la larghezza/altezza dell'immagine da mostrare. Non lo voglio però in 'testo grezzo' per il mondo da vedere. Ovviamente base64 può essere decisa da chiunque, ma non vogliamo che la tua joe media raccolga il percorso dell'URL. Ho davvero bisogno di recuperare: url, larghezza, altezza in una singola richiesta GET.

+2

C'è qualche motivo particolare per non utilizzare invece il POST o le sessioni? Sono molto più adatti per il passaggio di blocchi di dati di dimensioni corrette tra le pagine –

+0

Non è davvero possibile utilizzare post (penso comunque). Viene utilizzato per ottenere un'immagine e le sue dimensioni (che si trovano in una matrice serializzata all'interno della stringa codificata). Deve funzionare con un tag html standard . – Sk446

+0

Sono confuso. Stai inviando l'immagine dal server o dal browser? –

risposta

3

Gli URL non sono pensati per inviare lunghe stringhe di dati, codificati o non codificati. Dopo un certo punto, quando hai a che fare con una quantità così grande di dati inviati attraverso l'URL, dovresti iniziare a usare POST o qualche forma di archiviazione locale. FYI, IE ha un limite URL di 2038 caratteri.


EDIT: Non capisco una cosa. Perché non stai memorizzando nella cache le schermate? Sembra terribilmente dispendioso in termini di risorse dover prendere un nuovo screenshot ogni volta che qualcuno visualizza una pagina con un link IMG a quell'URL.

Forse il tuo pubblico è piccolo e le risorse non sono un problema. Tuttavia, se è l'opposto e in effetti è un sito web pubblico, questo non si ridimensionerà molto bene. So che sto andando oltre ciò che la tua domanda iniziale ha chiesto, ma questo risolverà la tua domanda e altro ancora.

Non appena il sito Web viene pubblicato, archiviare l'url in una sorta di archivio locale, preferibilmente in sql. Ho intenzione di continuare questo esempio come se scegli SQL, ma ovviamente la tua implementazione è la tua scelta. Avrei una chiave primaria, un campo url e un timestamp last_updated e facoltativamente un percorso di anteprima dell'immagine.

Utilizzando la memoria locale, è ora possibile estrarre l'immagine da una copia memorizzata nella cache memorizzata localmente sul server ogni volta che viene richiesta la pagina con la miniatura. Una quantità significativa di risorse viene salvata e poiché è probabile che tali siti Web non vengano aggiornati molto spesso, è possibile avere un cron job o uno script che esegue ogni x quantità di tempo per aggiornare gli screenshot nell'intero database. Ora, tutto ciò che devi fare è collegare direttamente (di nuovo dipende dalla tua implementazione) all'immagine e nessuna di questa enorme stringa di url succederà.

O, basta prendere la via più facile e farlo lato client con http://www.snap.com/

+0

I webservices REST-ish con querystrings possono sicuramente implementare il back-end e la cache HTTP. Per esempio. API grafico di Google. –

+2

Questo è un ottimo modo per non rispondere alla domanda, ben fatto. – Deji

1

Basta non base64_encode($whole_file). Invia il contenuto in blocchi e codifica i blocchi. Inoltre, se devi sapere quanto più grande può essere il tuo chunk dopo una chiamata allo base64_encode(), sarà più che doppio (2.1*strlen($chunk))

+2

Il rapporto è piuttosto 4/3, o 4 · ceil (n/3) se si aggiunge il riempimento finale. – Gumbo

1

Puoi ancora usare il POST per ciò che descrivi assumendo che ho capito bene, Potrei non averlo

Sto indovinando che stai facendo qualcosa di simile:

<a href="scripturl?w=11&h=100&url=really-long-secret-base64"> 
    <img src="imgurl"> 
</a> 

invece fare qualcosa di simile:

<form method="POST" action="scripturl"> 
    <input type="hidden" name="width" value="100"> 
    <input type="hidden" name="height" value="100"> 
    <input type="hidden" name="url" value="secret-url-string-here"> 
    <input type="image" src="imgurl" name="submit"> 
</form> 
0

è lo script che genera gli URL in esecuzione su un server diverso da quello script che li interpreta? Se si trovano sullo stesso server, l'approccio ovvio sarebbe archiviare l'URL, la larghezza e l'altezza di destinazione in un database e semplicemente passare un identificatore di record generato in modo casuale nella stringa di query.

5

Poiché si utilizza solo base64 per offuscare la stringa, è possibile solo offuscarla con qualcos'altro, come rot13 (o la propria funzione di sostituzione di lettere semplici). Quindi, urlencode(str_rot13($str)) da codificare e str_rot13(urldecode($str)) da decodificare.

Oppure, per avere solo una stringa con base64 codificata più breve, è possibile comprimere la stringa prima della codifica in base 64: base64_encode(gzencode($str, 9)) e gzdecode(base64_decode($str)) da decodificare.

Oppure, se questo è principalmente un problema di sicurezza (non ti dispiace che le persone vedano l'URL, vuoi semplicemente impedire alle persone di hackerarlo) potresti passare questi parametri con normali variabili di querystring, ma con un hash aggiunto a prevenire manomissioni vale a dire:

function getHash($url, $width, $height) { 
    $secret = 'abcdefghijklmnopqrstuvwxyz whatever you want etc.'; 
    return sha1($url . $width . $height . $secret); 
} 

// So use this hash to to construct your URL querystring: 
$hash = getHash($url, $width, $height); 
$urlQuerystring = '?url='.urlencode($url).'&width='.(int) $width. 
        '&height='.(int) $height.'&hash='.$hash; 

// Then in your code that processes the URL, check the hash first 
if ($hash != getHash($url, $width, $height)) 
    // URL is invalid 

(Off topic:. La gente dice che si dovrebbe usare POST invece di GET Se tutti questi URL stanno facendo è andare a prendere le immagini dal database per visualizzare (ad esempio una ricerca di ricerca), quindi ottenere va bene e ma se chiamare questi URL sta effettivamente eseguendo un'azione come andare su un altro sito, creando e archiviando lo screenshot, allora questo è un POST. Come suggerisce il loro nome, GET è per il recupero, il POST è per l'invio di dati. OTTIENI un'operazione costosa come fare lo screenshot, potresti finire a DOSare il tuo sito quando Google ecc. Indicizza questi URL.)

2

Sembra che i tuoi obiettivi siano 1. a visivamente oscurare un URL e 2. in genere codificare i dati in modo compatto per l'utilizzo in un URL.

In primo luogo, dobbiamo oscurare l'URL. Poiché gli URL utilizzano gran parte del dizionario Base64, qualsiasi codifica che produca file binari (che quindi deve essere Base64-ed) probabilmente aumenterà le dimensioni. È preferibile mantenere il dizionario nell'intervallo sicuro da URL con il minimo bisogno di escape quando viene applicato urlencode(). Cioè si desidera che questo:

/** 
* Rot35 for URLs. To avoid increasing size during urlencode(), commonly encoded 
* chars are mapped to more rarely used chars (end of the uppercase alpha). 
* 
* @param string $url 
* @return string 
*/ 
function rotUrl($url) { 
    return strtr($url, 
     'abcdefghijklmnopqrstuvwxyz0-:/?=&%#123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
     '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0-:/?=&%#'); 
} 

Ora, per il salvataggio di byte, si può codificare lo schema URL in un char (diciamo, h per HTTP, HTTPS per H), e convertire le dimensioni nella base 32. Wrapping questo in su:

function obscure($width, $height, $url) { 
    $dimensions = base_convert($width, 10, 32) . "." 
       . base_convert($height, 10, 32) . "."; 
    preg_match('@^(https?)://(.+)@', $url, $m); 
    return $dimensions . (($m[1] === 'http') ? 'h' : 'H') . rotUrl($m[2]); 
} 

function unobscure($str) { /* exercise for the reader! */ } 

$url = 'https://en.wikipedia.org/w/index.php?title=Special%3ASearch&search=Base64'; 
$obs = obscure(550, 300, $url); 
// h6.9c.H5E.N9B9G5491.FI7UNU9E45O.G8GVK9KC5W-G5391CYcj-51I38XJ51I38Wk1J5fd 

Dal momento che abbiamo evitato caratteri non sicuro per le URL, se questo viene messo in una querystring (con urlencode), non cresce molto (in questo caso non a tutti).

Inoltre, è possibile che si desideri firmare questa stringa in modo che le persone che conoscono la codifica non possano ancora specificare i propri parametri tramite l'URL. Per questo useresti HMAC e Base64URL-encoding l'hash. Puoi anche solo mantenere una sottostringa dell'hash (~ 6 bit per carattere) per risparmiare spazio.sign() (sotto) aggiunge un carattere 8 MAC (48 bit dell'hash a 6 bit/char):

function sign($key, $data) { 
    return $data . _hmac($key, $data, 8); 
} 
function verify($key, $signed) { 
    $mac = substr($signed, -8); 
    $data = substr($signed, 0, -8); 
    return $mac === _hmac($key, $data, 8) ? $data : false; 
} 
function _hmac($key, $data, $macLength) { 
    $mac = substr(base64_encode(hash_hmac('sha256', $data, $key, true)), 0, $macLength); 
    return strtr($mac, '+/', '-_'); // for URL 
} 

$key = "Hello World!"; 
$signed = sign($key, $obs); // appends MAC: "w-jjw2Wm" 

$obs = verify($key, $signed); // strips MAC and returns valid data, or FALSE 

Modifica: una migliore RotURL function.

+0

Questa è l'unica 'risposta' qui. Le altre risposte si riferiscono alla sicurezza che il richiedente specificatamente ha detto non è importante, o semplicemente cercano di argomentare contro la domanda stessa. Questa risposta, tuttavia, è utile per le persone che vengono a cercare questa domanda specifica. – Deji