¿Cómo se crea una cadena aleatoria adecuada para una ID de sesión en PostgreSQL?

Me gustaría crear una cadena aleatoria para usar en la verificación de la sesión usando PostgreSQL. Sé que puedo obtener un número aleatorio con SELECT random() , así que probé SELECT md5(random()) , pero eso no funciona. ¿Cómo puedo hacer esto?

Sugeriría esta solución simple:

Esta es una función bastante simple que devuelve una cadena aleatoria de la longitud dada:

 Create or replace function random_string(length integer) returns text as $$ declare chars text[] := '{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}'; result text := ''; i integer := 0; begin if length < 0 then raise exception 'Given length cannot be less than 0'; end if; for i in 1..length loop result := result || chars[1+random()*(array_length(chars, 1)-1)]; end loop; return result; end; $$ language plpgsql; 

Y el uso:

 select random_string(15); 

Ejemplo de salida:

 select random_string(15) from generate_series(1,15); random_string ----------------- 5emZKMYUB9C2vT6 3i4JfnKraWduR0J R5xEfIZEllNynJR tMAxfql0iMWMIxM aPSYd7pDLcyibl2 3fPDd54P5llb84Z VeywDb53oQfn9GZ BJGaXtfaIkN4NV8 w1mvxzX33NTiBby knI1Opt4QDonHCJ P9KC5IBcLE0owBQ vvEEwc4qfV4VJLg ckpwwuG8YbMYQJi rFf6TchXTO3XsLs axdQvaLBitm6SDP (15 rows) 

Puedes arreglar tu bash inicial así:

 SELECT md5(random()::text); 

Mucho más simple que algunas de las otras sugerencias. 🙂

Sobre la base de la solución de Marcin, podría hacer esto para utilizar un alfabeto arbitrario (en este caso, los 62 caracteres alfanuméricos ASCII):

 SELECT array_to_string(array ( select substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', trunc(random() * 62)::integer + 1, 1) FROM generate_series(1, 12)), ''); 

Puede obtener 128 bits de forma aleatoria de un UUID. Este es el método para hacer el trabajo en PostgreSQL moderno.

 CREATE EXTENSION pgcrypto; SELECT gen_random_uuid(); gen_random_uuid -------------------------------------- 202ed325-b8b1-477f-8494-02475973a28f 

Puede valer la pena leer los documentos en UUID también

El tipo de datos uuid almacena identificadores únicos universales (UUID) como se define en RFC 4122, ISO / IEC 9834-8: 2005 y estándares relacionados. (Algunos sistemas se refieren a este tipo de datos como un identificador global único, o GUID, en su lugar.) Este identificador es una cantidad de 128 bits que se genera mediante un algoritmo elegido para que sea muy poco probable que el mismo identificador sea generado por cualquier otra persona en el universo conocido usando el mismo algoritmo. Por lo tanto, para los sistemas distribuidos, estos identificadores proporcionan una mejor garantía de exclusividad que los generadores de secuencias, que son únicos dentro de una única base de datos.

¿Qué tan raro es una colisión con UUID o adivinable? Suponiendo que son al azar,

Se necesitarían aproximadamente 100 billones de UUID versión 4 para tener un 1 en mil millones de probabilidad de un solo duplicado (“colisión”). La probabilidad de una colisión aumenta al 50% solo después de que se hayan generado 261 UUID (2.3 x 1018 o 2.3 quintillones). Relacionando estos números con las bases de datos, y considerando la cuestión de si la probabilidad de una colisión UUID de la Versión 4 es despreciable, considere un archivo que contenga 2.3 quintillones Versión 4 UUID, con un 50% de posibilidades de contener una colisión UUID. Tendría 36 exabytes de tamaño, suponiendo que no hay otros datos o gastos generales, miles de veces más grandes que las bases de datos más grandes que existen en la actualidad, que están en el orden de los petabytes. A razón de mil millones de UUID generados por segundo, llevaría 73 años generar los UUID para el archivo. También requeriría alrededor de 3,6 millones de discos duros de 10 terabytes o cartuchos de cinta para almacenarlo, suponiendo que no hay copias de seguridad o redundancia. Leer el archivo a una tasa de transferencia típica de “disco a buffer” de 1 gigabit por segundo requeriría más de 3000 años para un único procesador. Dado que la tasa de error de lectura irrecuperable de las unidades es de 1 bit por cada 1018 bits, en el mejor de los casos, mientras que el archivo contendrá unos 1020 bits, leer el archivo una vez de un extremo a otro daría como resultado unas 100 veces más errores. leer UUIDs que duplicados. El almacenamiento, la red, la alimentación y otros errores de hardware y software serían, sin duda, miles de veces más frecuentes que los problemas de duplicación UUID. – fuente wikipedia

En resumen,

  • UUID está estandarizado.
  • gen_random_uuid() es 128 bits de aleatorio almacenados en 128 bits (2 ** 128 combinaciones). 0-desperdicio
  • random() solo genera 52 bits de aleatorio en PostgreSQL (2 ** 52 combinaciones).
  • md5() almacenado como UUID es de 128 bits, pero solo puede ser tan aleatorio como su entrada ( 52 bits si usa random() )
  • md5() almacenado como texto tiene 288 bits, pero solo puede ser tan aleatorio como su entrada ( 52 bits si usa random() ) – más del doble del tamaño de un UUID y una fracción de la aleatoriedad.
  • md5() como hash, puede optimizarse tanto que no hace mucho.
  • UUID es altamente eficiente para el almacenamiento: PostgreSQL proporciona un tipo que es exactamente de 128 bits. A diferencia de text y varchar , etc. que almacenan como varlena que tiene una sobrecarga para la longitud de la cadena.
  • El UUID ingenioso de PostgreSQL viene con algunos operadores, piezas fundidas y características por defecto.

Estuve jugando con PostgreSQL recientemente, y creo que encontré una solución un poco mejor, usando solo métodos PostgreSQL incorporados, no pl / pgsql. La única limitación es que actualmente solo genera cadenas, números o minúsculas de UPCASE.

 template1=> SELECT array_to_string(ARRAY(SELECT chr((65 + round(random() * 25)) :: integer) FROM generate_series(1,12)), ''); array_to_string ----------------- TFBEGODDVTDM template1=> SELECT array_to_string(ARRAY(SELECT chr((48 + round(random() * 9)) :: integer) FROM generate_series(1,12)), ''); array_to_string ----------------- 868778103681 

El segundo argumento para el método generate_series determina la longitud de la cadena.

Si bien no está activo de forma predeterminada, puede activar una de las extensiones principales:

 CREATE EXTENSION IF NOT EXISTS pgcrypto; 

Entonces su extracto se convierte en una simple llamada a gen_salt () que genera una cadena aleatoria:

 select gen_salt('md5') from generate_series(1,4); gen_salt ----------- $1$M.QRlF4U $1$cv7bNJDM $1$av34779p $1$ZQkrCXHD 

El número principal es un identificador hash. Varios algoritmos están disponibles cada uno con su propio identificador:

  • md5: $ 1 $
  • bf: $ 2a $ 06 $
  • des: no identificador
  • xdes: _J9 ..

Más información sobre extensiones:


EDITAR

Según lo indicado por Evan Carrol, a partir de v9.4 puede usar gen_random_uuid()

http://www.postgresql.org/docs/9.4/static/pgcrypto.html

Por favor use string_agg !

 SELECT string_agg (substr('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', ceil (random() * 62)::integer, 1), '') FROM generate_series(1, 45); 

Estoy usando esto con MD5 para generar un UUID también. Solo quiero un valor aleatorio con más bits que un entero random () .

No creo que estés buscando una cadena aleatoria per se. Lo que necesitaría para la verificación de la sesión es una cadena que se garantiza que es única. ¿Almacena información de verificación de sesión para auditar? En ese caso, necesita que la cadena sea única entre sesiones. Conozco dos enfoques bastante simples:

  1. Usa una secuencia Bueno para usar en una única base de datos.
  2. Use un UUID. Universalmente único, muy bueno en entornos distribuidos también.

Los UUID tienen la garantía de ser únicos en virtud de su algoritmo de generación; efectivamente, es extremadamente improbable que genere dos números idénticos en cualquier máquina, en cualquier momento, nunca (tenga en cuenta que esto es mucho más fuerte que en cadenas aleatorias, que tienen una periodicidad mucho más pequeña que los UUID).

Debe cargar la extensión uuid-ossp para usar los UUID. Una vez instalado, llame a cualquiera de las funciones uuid_generate_vXXX () disponibles en sus llamadas SELECT, INSERT o UPDATE. El tipo de uuid es un número de 16 bytes, pero también tiene una representación de cadena.

select * from md5(to_char(random(), '0.9999999999999999'));

El parámetro INTEGER define la longitud de la cadena. Garantizado para cubrir los 62 caracteres alfanuméricos con la misma probabilidad (a diferencia de otras soluciones que flotan en Internet).

 CREATE OR REPLACE FUNCTION random_string(INTEGER) RETURNS TEXT AS $BODY$ SELECT array_to_string( ARRAY ( SELECT substring( '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' FROM (ceil(random()*62))::int FOR 1 ) FROM generate_series(1, $1) ), '' ) $BODY$ LANGUAGE sql VOLATILE; 

@Kavius ​​recomendó usar pgcrypto , pero en lugar de gen_salt , ¿qué pasa con gen_random_bytes ? ¿Y qué tal sha512 lugar de md5 ?

 create extension if not exists pgcrypto; select digest(gen_random_bytes(1024), 'sha512'); 

Documentos:

F.25.5. Funciones de datos aleatorios

gen_random_bytes (count integer) devuelve bytea

Las devoluciones cuentan bytes aleatorios criptográficamente fuertes. Se pueden extraer 1024 bytes a la vez. Esto es para evitar el drenaje del grupo generador de aleatoriedad.

 select encode(decode(md5(random()::text), 'hex')||decode(md5(random()::text), 'hex'), 'base64')