2010-09-27 7 views
6

Me escribo un script que básicamente me permite enviar una URL y dos dimensiones enteras en la cadena de consulta de una única solicitud de obtención. Estoy usando base64 para codificarlo, pero es bastante largo y me preocupa que la URL se vuelva demasiado grande.PHP: ¿codificación más corta/oscurecida para una URL incrustada en otra URL?

¿Alguien conoce un método alternativo y más corto para hacer esto? Necesita ser decodificable cuando se recibe en una solicitud de obtención, por lo que md5/sha1 no son posibles.

Gracias por su tiempo.


Edición: Lo siento - Yo debería haber explicado mejor: Ok, en nuestro sitio nos muestran capturas de pantalla de sitios web que llegan a ser destinadas para su revisión. Tenemos nuestro propio servidor de miniaturas/captura de pantalla. Básicamente voy a hacer que la etiqueta de imagen contenga una cadena codificada que almacena la URL para tomar una captura de pantalla y el ancho/alto de la imagen para mostrar. No obstante, no lo quiero en 'texto sin formato' para que el mundo lo vea. Obviamente, base64 puede ser decidido por cualquier persona, pero no queremos que su promedio joe recoja la ruta de la URL. Realmente necesito buscar: url, ancho, alto en una sola solicitud GET.

+2

¿Hay alguna razón en particular para no usar POST o Sesiones en su lugar? Son mucho más adecuados para pasar trozos de datos de tamaño justo entre las páginas –

+0

No es posible utilizar la publicación (creo que de todos modos). Se usa para obtener una imagen y sus dimensiones (que están en una matriz serializada dentro de la cadena codificada). Tiene que funcionar con una etiqueta estándar html . – Sk446

+0

Estoy confundido. ¿Estás enviando la imagen desde el servidor o desde el navegador? –

Respuesta

3

Las URL no están destinadas a enviar largas cadenas de datos, codificadas o no codificadas. Después de cierto punto, cuando se trata de enviar grandes cantidades de datos a través de la URL, simplemente debe comenzar a usar POST o algún tipo de almacenamiento local. FYI, IE tiene un límite de URL de 2038 caracteres.


EDIT: No entiendo una cosa. ¿Por qué no estás almacenando en la memoria caché las capturas de pantalla? Parece terriblemente intensivo en recursos tener que tomar una nueva captura de pantalla cada vez que alguien ve una página con un enlace IMG a esa url.

Tal vez su audiencia es pequeña, y los recursos no son un problema. Sin embargo, si es lo contrario y de hecho es un sitio web público, no se escalará muy bien. Sé que voy más allá de lo que hizo su pregunta original, pero esto resolverá su pregunta y más.

Tan pronto como se publique el sitio web, almacene la url en algún tipo de almacenamiento local, preferiblemente en sql. Voy a continuar este ejemplo como si eligiera SQL, pero por supuesto su implementación es su elección. Tendría una clave principal, un campo url y la última marca de tiempo actualizada y, opcionalmente, una ruta de vista en miniatura de la imagen.

Al utilizar el almacenamiento local, ahora puede extraer la imagen de una copia en caché almacenada localmente en el servidor cada vez que se solicita la página con la miniatura. Se guarda una cantidad significativa de recursos, y dado que es probable que esos sitios web no se actualicen con mucha frecuencia, puede tener un trabajo cron o un script que se ejecute cada x período de tiempo para actualizar las capturas de pantalla en toda la base de datos. Ahora, todo lo que tienes que hacer es vincular directamente (de nuevo esto depende de tu implementación) a la imagen y ninguna de estas enormes cadenas de url sucederá.

O, simplemente, tomar el camino más fácil y hacerlo del lado del cliente con http://www.snap.com/

+0

Los servicios web REST-ish con querystrings ciertamente pueden implementar el back-end y el almacenamiento en caché de HTTP. P.ej. API de gráficos de Google. –

+2

Esta es una gran manera de no responder a la pregunta, bien hecho. – Deji

1

Eso sí, no base64_encode($whole_file). Envíe el contenido en trozos y codifique los trozos. Además, si usted debe saber cómo grande su porción puede conseguir después de una llamada a base64_encode(), que será más del doble de tamaño (pero menos de 2.1*strlen($chunk))

+2

La proporción es más bien 4/3 o 4 · ceil (n/3) si agrega el relleno posterior. – Gumbo

1

También puede usar la POST para lo que usted describe suponiendo que entendí su forma correcta, Puede que no tenga.

supongo que estás haciendo algo como esto:

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

en vez de hacer algo como esto:

<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

es el script que genera las direcciones URL que se ejecutan en un servidor diferente de la script que los interpreta? Si están en el mismo servidor, el enfoque obvio sería almacenar el URL objetivo, el ancho y el alto en una base de datos, y simplemente pasar un identificador de registro generado aleatoriamente en la cadena de consulta.

5

Dado que solo está utilizando base64 para oscurecer la cadena, podría ofuscarla con otra cosa, como rot13 (o su propia función de sustitución de letras). Entonces, urlencode(str_rot13($str)) para codificar y str_rot13(urldecode($str)) para decodificar.

O bien, para tener una cadena codificada en base64 más corta, puede comprimir la cadena antes de codificarla en base64: base64_encode(gzencode($str, 9)) y gzdecode(base64_decode($str)) para decodificar.

O, si esto es principalmente un problema de seguridad (no le molesta que la gente vea la URL, solo quiere evitar que la gente la piratee) puede pasar estos parámetros con variables normales de la cadena de consulta, pero con un hash agregado a prevenir la manipulación. es decir:

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 

(Fuera de tema:. La gente está diciendo que debe utilizar la POST en lugar de GET Si todas estas URLs están haciendo es ir a buscar imágenes de su base de datos para mostrar (es decir, una búsqueda de búsqueda), entonces se obtiene es fina y correcto. Pero si llamar a estas URL es en realidad realizar una acción como ir a otro sitio, hacer y almacenar la captura de pantalla, entonces eso es un POST. Como sugieren sus nombres, GET es para recuperación, POST es para enviar datos. OBTENER en una operación costosa como hacer la captura de pantalla, puede terminar con DOSing su propio sitio cuando Google, etc. indexe estas URL.)

2

Parece que sus objetivos son 1. a ocultar visualmente una URL, y 2. a generalmente codifican los datos de manera compacta para usarlos en una URL.

Primero, necesitamos ocultar la URL. Como las URL usan gran parte del diccionario Base64, cualquier codificación que produzca código binario (que luego tiene que ser Base64-ed) probablemente solo aumente el tamaño. Lo mejor es mantener el diccionario en el rango de URL segura con una mínima necesidad de escaparse cuando se aplica urlencode(). Es decir. desea que esta:

/** 
* 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-:/?=&%#'); 
} 

Ahora, para el ahorro de bytes, que puede codificar el esquema URL en un char (por ejemplo, h para HTTP, HTTPS para H), y convertir las dimensiones en la base 32. Envoltura esto:

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 

Desde evitamos caracteres no-URL seguro, si esto se pone en una cadena de consulta (con urlencode), que no crece mucho (en este caso no en todos).

Además, es posible que desee firmar esta cadena para que las personas que conocen la codificación todavía no puedan especificar sus propios parámetros a través de la URL. Para esto, usaría HMAC, y Base64URL-codificaría el hash. También puede mantener una subcadena del hash (~ 6 bits por carácter) para ahorrar espacio.sign() (abajo) añade un carácter 8 MAC (48 bits del hash de 6 bits/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 

Actualizar: una mejor RotURL function.

+0

Esta es la única 'respuesta' aquí. Las otras respuestas se centran en la seguridad que el autor de la pregunta dijo específicamente que no era importante, o simplemente tratan de argumentar en contra de la pregunta en sí. Esta respuesta, sin embargo, es útil para las personas que vienen a buscar esta pregunta específica. – Deji