Mi aplicación Rails necesidades para generar cupones electrónicos para los usuarios. Cada cupón determinado debe tener un único código de cupón que podrás canjear en nuestro sistema.

Por ejemplo un cupón para recibir un burrito. User A recibe un cupón para recibir un burrito y, a continuación, User B recibe un cupón para recibir un burrito. El 2 cupones únicos códigos de cupón.

¿Cuál es la mejor manera de generar un código como este que no es muy fácil de falsificar? No quiero que los usuarios tengan una alta tasa de éxito de escribir los números aleatorios y redimir a otros pueblos cupones.

Supongo que pensando en ello como una tarjeta de regalo con un número único en la espalda es lo que estoy buscando.

Es el código para el uso de la máquina (por ejemplo, en la Url) o supuesta a ser escrito por la mano de una impresión, o algo entre (algo que espera un usuario de corte & paste, y no es difícil de hacer)?
escrito por la mano de una impresión.
Eric Lippert muestra cómo hacer esto utilizando un inverso multiplicativo. Consulte Un uso práctico de los inversos multiplicativos. Una vez que ha generado la inversa, a continuación, puede codificar usando la Base de 64 o 36 Base, o lo que te guste..

OriginalEl autor Deekor | 2014-03-11

7 Comentarios

  1. 39

    El código debe ser imposible de adivinar, porque la única verificación se puede realizar antes de dar el usuario y su recompensa es comprobar si el código que entró existe en su lista de «dictado» de los códigos.

    • Que significa que el número de todos los códigos posibles en que formato es mucho mayor que el número de códigos que se desea emitir,. Dependiendo de cuán fácil es simplemente tratar de códigos (piense en una secuencia de comandos de intentar una y otra vez), entonces usted puede ser que necesite todos los códigos posibles a superar emitido códigos por un factor de un millón o mil millones o más. Esto suena alto, pero es posible que en un plazo relativamente corto de cadenas.

    • También significa que los códigos que se utilizan deben ser elegidos al azar dentro de todos los códigos posibles. Esto es necesario para evitar que los usuarios averiguar que la mayoría de los códigos válidos de inicio con «AAA», por ejemplo. Usuarios más sofisticados podrían irregular que su «random» códigos de usar un hackeable generador de números aleatorios (Ruby por defecto de rand() es rápido y estadísticamente bueno para datos aleatorios, pero es hackeable de esta manera, así que no lo use).

    El punto de partida para un código seguro sería la salida de una de cifrado PRNG. Ruby tiene la securerandom de la biblioteca, que puede utilizar para obtener una materia prima código como este:

    require 'securerandom'
    SecureRandom.hex
    # => "78c231af76a14ef9952406add6da5d42"

    Este código es lo suficientemente largo para cubrir cualquier número realista de los comprobantes de pago (millones cada uno para todos en el planeta), sin ningún sentido de probabilidad de repetición o de ser fáciles de adivinar. Sin embargo, es un poco incómodo para escribir a partir de una copia física.

    Una vez que sabes cómo generar un azar, prácticamente imposible de adivinar el código, el siguiente problema es la comprensión de la experiencia de usuario y decidir cuánto usted realmente puede poner en peligro la seguridad en el nombre de la usabilidad. Usted necesita para tener en cuenta el valor para el usuario final, y por lo tanto lo difícil que alguien podría tratar de conseguir un código válido. No puedo responder a eso, pero se pueden hacer algunas consideraciones generales acerca de la usabilidad:

    • Evitar personajes ambiguos. En la impresión, a veces es difícil ver la diferencia entre 1, I y l por ejemplo. A menudo nos entender lo que se supone que debe ser de contexto, pero un estudio aleatorizado cadena de caracteres que no tienen este contexto. Sería una mala experiencia de usuario a los que tenga que probar varias variaciones de un código de prueba de 0 vs O, 5 vs S etc.

    • Uso, ya sea en mayúsculas o en minúsculas las letras pero no tanto. Caso de que la sensibilidad no se entiende o es seguido por algunos %edad de los usuarios.

    • Aceptar variaciones en la coincidencia de los códigos. Permitir que los espacios y guiones. Tal vez incluso permitir 0 y O para significar la misma cosa. Esto se logra mejor mediante el procesamiento de la entrada de texto por lo que es en la caja derecha, tira de caracteres separadores, etc.

    • En la impresión, separar el código en un par de piezas pequeñas, será más fácil para el usuario encontrar su lugar en la cadena y tipo de unos personajes a la vez.

    • No hacer que el código sea demasiado largo. Yo sugeriría 12 caracteres, en 3 grupos de 4.

    • Esto es interesante – usted lo desea, puede escanear el código para que sea posible las palabras malsonantes, o evitar que los personajes que se generan. Si el código contenía sólo los caracteres K, U, F, C, entonces habría una alta probabilidad de ofender a un usuario. Esto no suele ser un motivo de preocupación porque los usuarios no ven la mayoría de los equipo seguro códigos, pero estos serán en la impresión!

    Poner que todos juntos, esta es la forma en que podría generar un utilizable código:

    # Random, unguessable number as a base20 string
    #  .reverse ensures we don't use first character (which may not take all values)
    raw_string = SecureRandom.random_number( 2**80 ).to_s( 20 ).reverse
    # e.g. "3ecg4f2f3d2ei0236gi"
    
    
    # Convert Ruby base 20 to better characters for user experience
    long_code = raw_string.tr( '0123456789abcdefghij', '234679QWERTYUPADFGHX' )
    # e.g. "6AUF7D4D6P4AH246QFH"
    
    
    # Format the code for printing
    short_code = long_code[0..3] + '-' + long_code[4..7] + '-' + long_code[8..11]
    # e.g. "6AUF-7D4D-6P4A"

    Hay 20**12 códigos válidos en este formato, lo que significa que puede emitir un mil millones de dólares de sus propios códigos, y que habría una en cuatro millones de posibilidades de que un usuario simplemente adivinando una correcta. En la criptografía círculos que sería muy malo (este código es inseguro contra un rápido ataque local), pero para un formulario web que ofrecen gratis burritos para usuarios registrados, y cuando usted se daría cuenta de que alguien tratando de cuatro millones de veces con una secuencia de comandos, es aceptar.

    OriginalEl autor Neil Slater

  2. 7

    Recientemente escribí cupón con código de gema que hace exactamente la misma cosa. El algoritmo tomado de Algoritmo::CouponCode módulo CPAN.

    Un código de cupón no sólo debe ser único, pero también es fácil de leer y de escribir mientras todavía está segura. Neil explicación y la solución es grande. Esta joya proporciona una forma conveniente de hacerlo y un bono de la característica de validación.

    >> require 'coupon_code'
    >> code = CouponCode.generate
    => "1K7Q-CTFM-LMTC"
    >> CouponCode.validate(code)
    => "1K7Q-CTFM-LMTC"
    >> CouponCode.validate('1K7Q-CTFM-LMTO') # Invalid code
    => nil

    OriginalEl autor baxang

  3. 4

    La clave para crear imposible de adivinar códigos de la cupón es de un gran espacio de códigos posibles con sólo una pequeña fracción de ellos son realmente válidos. Tomemos, por ejemplo, 8 caracteres alfanuméricos cadenas:

    alfanuméricos = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
    63 caracteres

    En este caso hay 63^8 = 248155780267521 códigos posibles. Esto significa que si usted emitir un mil millones de códigos la probabilidad de adivinar un código será 10^9/63^8 = 0.000004... – 4 en un millón.

    Sin embargo, no impiden la ejecución de un script que sigue intentando hasta que se descubre un código válido. Con el fin de bloquear un ataque de fuerza bruta deberá contar intentos por usuario y la prohibición sobre algún límite.

    Si usted está buscando para una biblioteca que permite una completa personalización de la salida de los códigos de cupón (longitud, caracteres, prefijo, sufijo y el patrón) echa un vistazo a vale-generador de código-js – es una librería escrita en JavaScript. Ejemplo de uso:

    voucher_codes.generate({
        length: 8,
        count: 1000,
    });

    Generará 1000 azar códigos únicos, cada uno de los 8 caracteres de largo.

    Otro ejemplo:

    voucher_codes.generate({
        pattern: "###-###-###",
        count: 1000,
    });

    Generará 1000 azar códigos únicos siguiente patrón dado.

    El código fuente es relativamente simple. Apuesto a que usted puede fácilmente volver a escribir a cualquier otro idioma si el JS no es tu favorito 😉

    Si usted necesita una solución integral para los códigos de descuento de gestión (incluyendo ataques de fuerza bruta con la prevención de que usted puede estar interesado en Voucherify.

    OriginalEl autor Voucherify

  4. 1

    Ir con algo así como:

    class Coupon < ActiveRecord::Base
      before_save generate_token
    
      validates_uniqueness_of :token
    
      def generate_token
        self.token = "#{current_user.id}#{SecureRandom.urlsafe_base64(3)}"
      end
    
    end

    EDIT: Aquí es un mejor respuesta

    Me gustaría ir con SecureRandom.uuid como es más legible de la OMI

    OriginalEl autor Abram

  5. 0

    Por ejemplo, es posible utilizar un número al azar y comprobar si no se ha generado antes, almacenando todos los códigos válidos en una base de datos.

    Wouldnt que utilizan una gran cantidad de tiempo una vez que la base de datos tiene grandes?
    Usted tendrá que almacenar el código para almacenar los códigos que ya estaban acostumbrados. Si el uso de grandes números aleatorios colisiones será bastante raro.

    OriginalEl autor MrSmith42

  6. 0

    Sorteo de números aleatorios con una probada generador (http://en.wikipedia.org/wiki/List_of_pseudorandom_number_generators).

    Asumir que entregar 333 cupones por día y estos son válidos por 30 días. Así que usted tiene que guardar 10000 números y asegurarse de que un falsificador no puede encontrar uno por casualidad.

    Si tus números han de 10 dígitos significativos (~32 bits, ~8 dígitos hexadecimales), la probabilidad de un evento es uno de los más de un millón. Por supuesto, usted puede utilizar más.

    OriginalEl autor Yves Daoust

  7. 0

    Tuve una similar de casos de uso donde tenía que generar un único/no-repetición de código para cada objeto creado en el sistema(en esta pregunta, se trata de un cupón). Yo tenía los siguientes requisitos:

    • Yo quería que la longitud del código para ser tan corto como sea posible.
    • Lo que me di cuenta es que la longitud del código eventualmente ser al menos tan larga como el número de dígitos que determinar el recuento del número de objetos posibles. Por ejemplo. si usted genera 9999 cupones, el código de esencia, tiene que ser de al menos 4 dígitos de largo.
    • No debe ser secuencial /fácilmente adivinar.

    He explorado varios métodos para generar claves, incluyendo aquellas que son timestamp basado y se encontró que la mayoría de los métodos generar largo de los códigos. Por lo tanto, decidí emplear mi propia lógica de la siguiente manera.

    • Puedo crear una db tabla donde puedo crear un solo registro, el cual mantiene el recuento del número de objetos creados hasta la fecha en el sistema.
    • Luego me prefijo y el sufijo de este número con un carácter cada seleccionados al azar a partir de [a-zA-Z0-9]. Este paso asegura que aunque los números son secuenciales, no es posible adivinar el código, a menos que el prefijo y el sufijo se adivinan. Basado en [a-zA-Z0-9] conjunto de caracteres, no sería 3782 (62*61) posibilidades de un código. El anterior conjunto de caracteres que funciona para mí, pero usted es libre de utilizar un juego de caracteres de su elección. Algunas sugerencias se encuentran en la mejor respuesta de este hilo.
    • Cada vez que se crea un nuevo objeto que el número de objetos se incrementa de uno en uno en la db.

    En este enfoque el número de caracteres del código será determinado por:

    number of characters of ( count of objects in the system so far ) + 2

    Así que, cuando usted comienza número de caracteres será de 3, al llegar a los 10 objetos que serán 4, al llegar a los 100 objetos será de 5, para 1000 será 6 y así sucesivamente. De esta manera el sistema de la escala en su propia función del uso.

    Este enfoque funcionó mucho mejor de lo que en el caso de que se genera un código primero y, a continuación, comprobar si el código ya existente en la base de datos. En el caso de que usted mantenga la generación de códigos hasta encontrar un código que no está ya generado.

    OriginalEl autor Aneesh

Dejar respuesta

Please enter your comment!
Please enter your name here