php - soporta - optimizar consultas mysql explain
Estoy buscando una manera, específicamente en PHP, de que se me garantice que siempre obtengo una clave única.
He hecho lo siguiente:
strtolower(substr(crypt(time()), 0, 7));
Pero he descubierto que de vez en cuando termino con una clave duplicada (rara vez, pero con la suficiente frecuencia).
También he pensado en hacer:
strtolower(substr(crypt(uniqid(rand(), true)), 0, 7));
Pero de acuerdo con el sitio web PHP, uniqid () podría, si uniqid () se llama dos veces en el mismo microsegundo, podría generar la misma clave. Estoy pensando que la adición de rand () raramente lo haría, pero aún es posible.
Después de las líneas mencionadas anteriormente, también elimino caracteres como L y O, por lo que es menos confuso para el usuario. Esto quizás sea parte de la causa de los duplicados, pero sigue siendo necesario.
Una opción en la que tengo pensado es crear un sitio web que generará la clave, almacenándola en una base de datos, asegurando que sea completamente única.
¿Algún otro pensamiento? ¿Hay sitios web que ya hacen esto que tienen algún tipo de API o simplemente devuelven la clave. Encontré http://userident.com pero no estoy seguro si las claves serán completamente únicas.
Esto debe ejecutarse en segundo plano sin ninguna intervención del usuario.
Normalmente lo hago así:
$this->password = '''';
for($i=0; $i<10; $i++)
{
if($i%2 == 0)
$this->password .= chr(rand(65,90));
if($i%3 == 0)
$this->password .= chr(rand(97,122));
if($i%4 == 0)
$this->password .= chr(rand(48,57));
}
Supongo que hay algunos agujeros teóricos, pero nunca tuve un problema con la duplicación. Normalmente lo uso para contraseñas temporales (como después de restablecer una contraseña) y funciona lo suficientemente bien para eso.
Puede que le interese este artículo sobre el mismo problema: los GUID son globalmente únicos, pero las subcadenas de GUID no lo son .
El objetivo de este algoritmo es utilizar la combinación de tiempo y ubicación ("coordenadas espacio-temporales" para los geeks de relatividad) como la clave de exclusividad. Sin embargo, el cronometraje no es perfecto, por lo que existe la posibilidad de que, por ejemplo, se generen dos GUID en rápida sucesión desde la misma máquina, muy cerca el uno del otro a tiempo de que la marca de tiempo sea la misma. Ahí es donde entra el uniquifier.
Si usa su método original, pero agrega el nombre de usuario o emailaddress delante de la contraseña, siempre será único si cada usuario solo puede tener 1 contraseña.
Sin escribir el código, mi lógica sería:
Genere una cadena aleatoria de los caracteres aceptables que desee.
Luego agregue la mitad del sello de la fecha (segundos parciales y todo) al frente y la otra mitad al final (o en algún lugar en el medio, si lo prefiere).
¡Quédate JOLLY!
MARIDO
Suelo hacer una subcadena aleatoria (aleatorizar cuántos caracteres entre 8 y 32, o menos para comodidad del usuario) o el MD5 de algún valor que he obtenido, o la hora, o alguna combinación. Para obtener más aleatoriedad, hago MD5 del valor de vencimiento (por ejemplo, apellido) concatenar con el tiempo, MD5 de nuevo, luego tomar la subcadena aleatoria. Sí, podría obtener contraseñas iguales, pero no es muy probable en absoluto.
Todavía no veo por qué las contraseñas deben ser únicas. ¿Cuál es la desventaja si 2 de tus usuarios tienen la misma contraseña?
Esto supone que estamos hablando de contraseñas atadas a ID de usuario, y no solo identificadores únicos. Si eso es lo que está buscando, ¿por qué no usar GUID?
Cualquier algoritmo dará como resultado duplicados .
Por lo tanto, ¿podría sugerirle que use su algoritmo * existente y simplemente verifique si hay duplicados?
* Una ligera adición: si uniqid()
puede ser no único en función del tiempo, también incluye un contador global que se incrementa después de cada invocación. De esa forma, algo es diferente incluso en el mismo microsegundo.
Creo que parte de su problema es que nos está tratando de una función singular para dos usos diferentes ... contraseñas y transaction_id
estos realmente son dos áreas problemáticas diferentes y realmente no es mejor intentar abordarlas juntas.
Puede que le interese la implementación segura de Steve Gibson de un generador de contraseñas (sin fuente, pero tiene una descripción detallada de cómo funciona) en https://www.grc.com/passwords.htm .
El sitio crea enormes contraseñas de 64 caracteres pero, dado que son completamente al azar, puede tomar fácilmente los primeros 8 (o tantos) caracteres para una contraseña menos segura pero "lo más aleatoria posible".
EDITAR: de sus respuestas posteriores veo que necesita algo más como un GUID que una contraseña, por lo que probablemente no sea lo que quiere ...
Recientemente quería una clave única aleatoria rápida y sencilla, así que hice lo siguiente:
$ukey = dechex(time()) . crypt( time() . md5(microtime() + mt_rand(0, 100000)) );
Entonces, básicamente, obtengo el tiempo de Unix en segundos y agrego una cadena md5 aleatoria generada a partir del tiempo + número aleatorio. No es lo mejor, pero para solicitudes de baja frecuencia es bastante bueno. Es rápido y funciona.
Hice una prueba en la que generaba miles de claves y luego buscaba repeticiones, y teniendo alrededor de 800 teclas por segundo no había repeticiones, así que no estaba mal. Supongo que depende totalmente de mt_rand ()
Lo uso para un rastreador de encuestas donde obtenemos una tasa de envío de aproximadamente 1000 encuestas por minuto ... así que por ahora (cruza los dedos) no hay duplicados. Por supuesto, la tasa no es constante (obtenemos los envíos en ciertos momentos del día) así que esto no es a prueba de fallas ni la mejor solución ... la sugerencia es usar un valor incremental como parte de la clave (en mi caso, Usé el tiempo (), pero podría ser mejor).
Engañar a la parte de criptación que no tiene mucho que ver con la creación de un valor único, generalmente uso este:
function GetUniqueValue()
{
static $counter = 0; //initalized only 1st time function is called
return strtr(microtime(), array(''.'' => '''', '' '' => '''')) . $counter++;
}
Cuando se llama en el mismo proceso $ counter se incrementa, por lo que el valor siempre es único en el mismo proceso.
Cuando se le llama en diferentes procesos debe ser realmente desafortunado al obtener 2 llamadas microtime () con los mismos valores, piense que las llamadas microtime () generalmente también tienen valores diferentes cuando se las llama en el mismo script.
Solo hay 3 formas de generar valores únicos, más bien son contraseñas, ID de usuario, etc.
- Use un generador de GUID efectivo: estos son largos y no se pueden reducir. Si solo usa una parte , NO FALLA .
- Al menos parte del número se genera secuencialmente fuera de una secuencia única. Puede agregar fluff o codificación para que parezca menos secuencial. La ventaja es que comienzan en corto, la desventaja es que requieren una sola fuente. La solución para la limitación de fuente única es tener fuentes numeradas, por lo que debe incluir [fuente #] + [seq #] y luego cada fuente puede generar su propia secuencia.
- Generarlos a través de otros medios y luego compararlos con el historial único de valores generados previamente.
Cualquier otro método no está garantizado. Tenga en cuenta que, fundamentalmente, está generando un número binario (es una computadora), pero luego puede codificarlo en hexadecimal, decimal, base64 o en una lista de palabras. Elija una codificación que se ajuste a su uso. Por lo general, para los datos ingresados por el usuario, usted desea alguna variación de Base32 (que usted insinuó).
Nota sobre GUIDS : ganan su fuerza de singularidad a partir de su longitud y el método utilizado para generarlos. Cualquier cosa inferior a 128 bits no es seguro. Más allá de la generación de números aleatorios, hay características que entran en un GUID para hacerlo más único. Tenga en cuenta que solo son prácticamente únicos, no completamente únicos. Es posible, aunque es prácticamente imposible tener un duplicado.
Nota actualizada sobre GUIDS : Desde que escribí esto, aprendí que muchos generadores GUID usan un generador de números aleatorios criptográficamente seguro (difícil o imposible de predecir el siguiente número generado, y que probablemente no se repita). En realidad, hay 5 algoritmos UUID diferentes. Algoritmo 4 es lo que Microsoft usa actualmente para la API de generación de GUID de Windows. Un GUID es la implementación de Microsoft del estándar UUID.
Actualización : si quieres 7 a 16 caracteres, entonces necesitas usar el método 2 o 3.
En pocas palabras: francamente no existe tal cosa como completamente único. Incluso si fuera con un generador secuencial eventualmente se quedaría sin almacenamiento usando todos los átomos del universo, volviendo a conectarse consigo mismo y repitiendo. Tu única esperanza sería la muerte térmica del universo antes de llegar a ese punto.
Incluso el mejor generador de números aleatorios tiene la posibilidad de repetir igual al tamaño total del número aleatorio que está generando. Tome un cuarto por ejemplo. Es un generador de bits completamente aleatorio, y sus probabilidades de repetir son 1 en 2.
Entonces todo se reduce a tu umbral de singularidad. Puede tener un 100% de exclusividad en 8 dígitos para 1,099,511,627,776 números usando una secuencia y luego base32 codificándolo. Cualquier otro método que no implique verificar contra una lista de números pasados solo tiene probabilidades equivalentes a n / 1,099,511,627,776 (donde n = número de números previos generados) de no ser únicos.