Mi colega y yo estamos debatiendo cuál de estos métodos a utilizar para la generación de auto IDENTIFICACIÓN del usuario y la ID del post de la identificación en la base de datos:

Una opción que se usa una sola instancia de Azar, y toma algunos parámetros útiles por lo que puede ser reutilizado para todo tipo de cadena de generación de casos (es decir, a partir de 4 dígitos numéricos de los pines de 20 dígitos alfanuméricos ids). Aquí está el código:

//This is created once for the lifetime of the server instance
class RandomStringGenerator
{
    public const string ALPHANUMERIC_CAPS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
    public const string ALPHA_CAPS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    public const string NUMERIC = "1234567890";

    Random rand = new Random();
    public string GetRandomString(int length, params char[] chars)
    {
        string s = "";
        for (int i = 0; i < length; i++)
            s += chars[rand.Next() % chars.Length];

        return s;
    }
}

y la otra opción es simplemente para usar:

Guid.NewGuid();

ver Guid.NewGuid en MSDN

Ambos estamos conscientes de que Guid.NewGuid() trabajo para nuestras necesidades, pero prefiero utilizar el método personalizado. Se hace lo mismo pero con más control.

Mi colega piensa que porque el método personalizado ha sido cocinado por nosotros mismos, es más probable que generan las colisiones. Admito que no soy plenamente consciente de la implementación de Azar, pero supongo que es tan aleatorio como el Guid.NewGuid(). Un uso típico de la costumbre método podría ser:

RandomStringGenerator stringGen = new RandomStringGenerator();
string id = stringGen.GetRandomString(20, RandomStringGenerator.ALPHANUMERIC_CAPS.ToCharArray());

Edit 1:

  • Estamos utilizando las Tablas de Azure que no tiene un incremento automático (o similar) de la característica para la generación de claves.
  • Algunas respuestas aquí solo dime a utilizar NewGuid() «porque eso es lo que hacen». Estoy buscando para un análisis más en profundidad la razón por la que el cocinado método puede ser más propensos a generar colisiones dado los mismos grados de libertad como un Guid.

Edit 2:

Estábamos usando también el cocinado método para generar el ID del post es que, a diferencia de los tokens de sesión, necesita estar guapa para mostrar en la url de nuestro sitio web (como http://mywebsite.com/14983336), así guid no son una opción, sin embargo, las colisiones son todavía debe ser evitado.

  • Random NO hace ninguna garantía de unicidad. Es perfectamente válido para una secuencia aleatoria para contener el resultado de la misma varias veces.
  • Si usted cocinar usted mismo, es menos probable que los ÚNICO, a continuación, un GUID. Un GUID hace uso de cierto tipo de hardware factores y el tiempo actual para generar un GUID. Usted puede investigar los detalles por sí mismo. Un GUID no será el único, si usted golpea el mismo GUID generador demasiado a menudo en un segmento corto de tiempo. De nuevo, usted puede ver los detalles por sí mismo.
  • Si desea generar Identificadores únicos del usuario y post Id, usted debe utilizar el auto-incremento de los números de una base de datos. Golpear la base de datos, obtener de vuelta el siguiente número en la secuencia. Único garantizado.
  • Como @GalacticCowboy dijo, al azar debe ser leído como un modo determinista al azar, no es único; si usted está buscando la singularidad, use NewGuid
  • No. Sólo 1 de tipo Guid hacer, y el Guid.NewGuid() devuelve un tipo 4 GUID.
  • «Admito que no soy plenamente consciente de la implementación de Azar, pero supongo que es tan aleatorio como Guid.NewGuid(). Tu suposición es totalmente incorrecta, de dos maneras. (1) Guid no están garantizados para ser al azar; son únicos. (2) la Versión 4 Guid son al azar (en la mayoría, pero no todos sus bits) y su fuente de entropía es mucho menos propenso a la colisión de la débil fuente de entropía utilizado por Random.
  • Se debe volver a escribir la pregunta para la que se pide explícitamente que el método es más probable que generan las colisiones si eso es todo lo que usted está después. La pregunta parece a preguntar cuál es la mejor opción.
  • donde en la documentación que hace el estado que NewGuid siempre devuelve una versión 4 guid?
  • Y mientras estamos viendo su código, IT_IS_NOT_1970_ANYMORE; FormatYourConstantsLikeThis en C#.
  • Voy a formatear mi código de cómo me gusta gracias! Capital letras ver más tenaz y más difícil de moverse, es decir, constante.
  • Usted puede encontrar la segunda mitad de Raymond Chen artículo sobre el acortamiento de un GUID para ser de su interés. blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx
  • Tienes razón, no dice que en la documentación. Ocurre en la práctica, sin embargo.
  • Si usted basado únicamente en el comportamiento documentado, el 90% de los .net framework sería inutilizable.
  • Re: formato: Se trata de la persona después de usted. La semántica de código de formato son muy subjetivas. A saber: el convenio original de todas las mayúsculas no tenía nada que ver con la forma de «terco» parecía – agregó que el significado, y no me gustaría leer de esa manera. Décadas de mantenimiento a través de múltiples equipos ha hecho que muchas personas prefieren ponerse de acuerdo sobre una convención en lugar de intentar interpretarlo en una base por línea. En C# existe una guía oficial, y los desarrolladores se espera que generalmente se adhieren a ella. Pero es off-topic, estoy de acuerdo.
  • Totalmente de acuerdo con usted. Mientras escribo estándar de C# el formato de todas partes, todavía puedo usar C++ macro-estilo de constante sólo porque es inmediatamente obvio que esto nunca va a cambiar en tiempo de ejecución…

7 Comentarios

  1. 50

    Estoy buscando para un análisis más en profundidad la razón por la que el cocinado método puede ser más propensos a generar colisiones dado los mismos grados de libertad como un Guid.

    Primero, como otros han señalado, Random no es thread-safe); el uso de múltiples hilos pueden causar a corromper a sus estructuras de datos internas de manera que siempre produce la misma secuencia.

    Segundo, Random es cabeza de serie basado en la hora actual. Dos instancias de Random creado dentro de la misma milésima de segundo (recuerden que un milisegundo es de varios millones de de ciclos de procesador en hardware moderno) tendrá la misma semilla, y por lo tanto va a producir la misma secuencia.

    Tercero, mentí. Random no es cabeza de serie basado en la hora actual; es cabeza de serie basado en la cantidad de tiempo que la máquina ha estado activo. La semilla es un número de 32 bits, y dado que la granularidad es en milisegundos, que es sólo un par de semanas hasta que lo envuelve. Pero ese no es el problema; el problema es: el período de tiempo en el cual se crea la instancia de Random es muy probable que sea dentro de un par de minutos de la máquina arranque. Cada vez que se encienda el ciclo de una máquina, o traer una nueva máquina en línea en un clúster, hay una pequeña ventana en la que las instancias de Azar son creados, y la más que pasa, mayor es la probabilidad de que usted va a obtener una semilla de la que tenía antes.

    (ACTUALIZACIÓN: Nuevas versiones de el .NET framework, han mitigado algunos de estos problemas; en esas versiones no tienen todos los Random creado dentro de la misma milésima de segundo tienen la misma semilla. Sin embargo, todavía hay muchos problemas con Random; siempre recuerde que es sólo pseudo-aleatorio, no cripto-resistencia al azar. Random en realidad es muy predecible, por lo que si usted está confiando en la imprevisibilidad, no es adecuado.)

    Como otros han dicho: si quieres una clave principal para la base de datos, a continuación, tiene la base de datos generar una clave principal; vamos a la base de datos hacer su trabajo. Si quieres un identificador único global, a continuación, usar un guid; que es lo que están buscando.

    Y por último, si usted está interesado en aprender más acerca de los usos y abusos de guid, a continuación, es posible que desee leer mi «guid» guía de la serie; la primera parte está aquí:

    http://blogs.msdn.com/b/ericlippert/archive/2012/04/24/guid-guide-part-one.aspx

    • Gracias por tu respuesta, el guid de la guía fue útil y su especulaciones en parte 3 nos llevan a generar nuestro propio ID y tokens de sesión utilizando RNGCryptoServiceProvider en lugar de NewGuid(). Ver mi propia respuesta a esta pregunta a continuación para obtener más detalles.
    • +1 por mentir, luego de admitir que mintió.
  2. 7

    Como está escrito en otras respuestas, mi aplicación tenido un par de problemas graves:

    • Hilo de seguridad: Azar no es seguro para subprocesos.
    • Previsibilidad: el método no podía ser utilizado para la seguridad de la crítica identificadores como tokens de sesión debido a la naturaleza de la clase al Azar.
    • Colisiones: aunque el método creado 20 ‘al azar’ números, la probabilidad de una colisión no es (number of possible chars)^20 debido a que el valor de la semilla sólo es el 31 de bits, y que venía de un mal de origen. Dada la misma semilla, cualquier longitud de la secuencia será la misma.

    Guid.NewGuid() estaría bien, excepto que no quiere usar feo Guid en las direcciones url y .Redes de NewGuid() algoritmo no es conocido por ser criptográficamente seguro para su uso en tokens de sesión – podría dar resultados predecibles si un poco de la información que se conoce.

    Aquí está el código que estamos usando ahora, es segura, flexible y por lo que yo sé es muy raro para crear colisiones si se les da suficiente longitud y carácter elección:

    class RandomStringGenerator
    {
        RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
        public string GetRandomString(int length, params char[] chars)
        {
            string s = "";
            for (int i = 0; i < length; i++)
            {
                byte[] intBytes = new byte[4];
                rand.GetBytes(intBytes);
                uint randomInt = BitConverter.ToUInt32(intBytes, 0);
                s += chars[randomInt % chars.Length];
            }
            return s;
        }
    }
    • Sólo por curiosidad: ¿no hay una ligera preferencia de ciertos elementos en chars cuando uint.MaxValue no es un múltiplo de chars.Length, porque se está utilizando el operador de módulo aquí? No sé si esto es relevante, aunque.
  3. 4

    «Auto de generación de identificadores de usuario y post identificadores para la identificación en la base de datos»…¿por qué no utilizar una base de datos de la secuencia o de identidad para generar las claves?

    A mí su pregunta es, realmente, «¿Cuál es la mejor manera para generar una clave principal en mi base de datos?» Si ese es el caso, debe utilizar la herramienta convencional de la base de datos que va a ser una secuencia o de identidad. Estos tienen ventajas sobre cadenas generadas.

    1. Secuencias/identidad índice mejor. Hay numerosos artículos y publicaciones en el blog que explique por qué Guid y así sucesivamente hacer buenos índices.
    2. Que están garantizados para ser único en la tabla
    3. Que puede ser de forma segura generado por inserciones simultáneas sin colisión
    4. Son fáciles de implementar

    Supongo que mi siguiente pregunta es, ¿qué razones usted está considerando GUID o cadenas generadas? Va a ser a través de la integración de bases de datos distribuidas? Si no, usted debe preguntarse si la solución de un problema que no existe.

    • Como nota, los Guid parecen ser los más útiles distribuido o desconectado-edición de escenarios. De lo contrario, estás más que nada por hacer más trabajo para usted sin ningún beneficio real.
    • Yo no veo el 2, 3 y 4 como grandes ventajas sobre el Guid o manualmente al azar generado por las cadenas(el uso de una buena PRNG). La probabilidad de colisión es insignificante. El punto 1 es la gran desventaja de azar IDs. Incluso con sistemas distribuidos machine-id + counter a menudo es preferible.
    • Estamos usando las tablas de Azure y acceder a ellos desde un azure web de rollo. Yo no soy experto en bases de datos, pero creo Guid/random cadenas son la única opción aquí?
    • Ah, eso cambia las cosas. Veo que has actualizado tu pregunta ahora a reflejar eso. En ese caso, remitir a Eric buena respuesta.
  4. 3

    Su método personalizado tiene dos problemas:

    1. Utiliza una instancia global de Random, pero no utilizan el bloqueo. => de Múltiples subprocesos de acceso puede dañar su estado. Después de que la salida va a chupar incluso más de lo que ya lo hace.
    2. Utiliza una predicción 31 de bits de la semilla. Esto tiene dos consecuencias:
      • No se puede utilizar para cualquier cosa relacionada con la seguridad, donde unguessability es importante
      • La pequeña semilla (31 bits) puede reducir la calidad de sus números. Por ejemplo, si desea crear varias instancias de Random al mismo tiempo(desde el inicio del sistema) que probablemente va a crear la misma secuencia de números aleatorios.

    Esto significa que usted no puede depender de la salida de Random de ser único, no importa cuan largo es.

    Recomiendo el uso de un CSPRNG (RNGCryptoServiceProvider) incluso si usted no necesita la seguridad. Su rendimiento es aceptable para la mayoría de los usos, y me gustaría confiar en la calidad de sus números aleatorios sobre Random. Si usted desea singularidad, recomiendo conseguir los números con alrededor de 128 bits.

    Para generar al azar cadenas utilizando RNGCryptoServiceProvider usted puede tener una mirada en mi respuesta a ¿Cómo puedo generar al azar de 8 caracteres, cadenas alfanuméricas en C#?.


    Hoy en día Guid devuelto por Guid.NewGuid() son de la versión 4 Guid. Que se generan a partir de un PRNG, por lo que tienen bastante de propiedades similares a la generación aleatoria de 122 número de bits (el resto de los 6 bits son fijos). Su entropía de la fuente tiene una calidad muy superior a lo que Random usos, pero no está garantizado para ser criptográficamente seguro.

    Pero el algoritmo de generación puede cambiar en cualquier momento, por lo que no se puede confiar en eso. Por ejemplo, en el pasado el GUID de Windows algoritmo de generación cambia de v1 (basado en MAC + timestamp) a v4 (al azar).

  5. 1

    Uso Sistema.Guid como:

    …puede ser utilizado en todos los ordenadores y redes siempre un identificador único que se requiere.

    Nota que Random es un pseudo-random number generator. No es realmente aleatorio, ni único. Sólo tiene 32 bits de valor para trabajar con, en comparación con la de 128 bits GUID.

    Sin embargo, incluso Guid puede haber colisiones (aunque las posibilidades son muy delgado), por lo que debe utilizar la base de datos de las características propias para darle un identificador único (por ejemplo, el incremento automático de IDENTIFICACIÓN de columna). También, usted puede fácilmente convertir un GUID en un 4 o 20 (alfa)numérico numérico.

    • Siendo pseudo-aleatorio no es un problema per se (v4 Guid son sólo números pseudo-aleatorios así), pero Random utiliza una muy mala semilla.
  6. 1

    Contrario a lo que algunas personas han dicho en el comentario, un GUID generado por el Guid.NewGuid() NO depende de ninguna máquina-identificador específico (sólo en el tipo 1 Guid, Guid.NewGuid() devuelve un tipo 4 GUID, que en su mayoría es al azar).

    Mientras usted no necesita la seguridad criptográfica, la Random de la clase debe ser lo suficientemente bueno, pero si quieres estar más seguro, use System.Security.Cryptography.RandomNumberGenerator. Para el Guid enfoque, tenga en cuenta que no todos los dígitos en un GUID son aleatorios. Cita de wikipedia:

    En la representación canónica, xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx, los bits más significativos de la N indica la variante (dependiendo de la variante; uno, dos o tres bits se utilizan). La variante cubiertos por el UUID de la especificación es indicado por los dos bits más significativos de N a 1 0 (es decir, el hexadecimal N siempre será 8, 9, a, B).
    En la variante cubiertos por el UUID de la especificación, hay cinco versiones. Para esta variante, los cuatro bits de la M indica el UUID de la versión (es decir, el hexadecimal M va a ser 1, 2, 3, 4, o 5).

  7. 0

    Con respecto a su edición, aquí es una razón para preferir un GUID a través de una cadena generada:

    El almacenamiento nativo para un GUID (uniqueidentifier) en SQL Server es de 16 bytes. Para almacenar un equivalente de longitud varchar (string), donde cada uno de los «dígitos» en el identificador se almacena como un personaje, requeriría algún lugar entre 32 y 38 bytes, dependiendo del formato.

    Debido a su almacenamiento, SQL Server también es capaz de indexar una columna uniqueidentifier de manera más eficiente que una columna varchar así.

    • La edición, dijo que no lo estoy usando SQL o de cualquiera de sus GUID características. Estoy usando las tablas de azure que necesita una cadena como una fila de clave.
    • «No apoyo uniqueidentifier» estás hablando de SQL azure o las tablas de Azure? Yo no estoy usando SQL azure, y no estoy seguro de lo que significan en términos de las tablas de Azure. editar: elimina tu comentario…
    • Sí, en la lectura más que he decidido que mi comentario (y, de hecho, toda esta respuesta) realmente no se aplican a su situación. En un caso general, la pregunta título y detalles son realmente acerca de dos cosas diferentes.

Dejar respuesta

Please enter your comment!
Please enter your name here