Создать GUID / UUID в JavaScript? - PullRequest
       582

Создать GUID / UUID в JavaScript?

3682 голосов
/ 20 сентября 2008

Я пытаюсь создать глобально уникальные идентификаторы в JavaScript. Я не уверен, какие подпрограммы доступны во всех браузерах, насколько «случайным» и затравленным является встроенный генератор случайных чисел и т. Д.

Значение GUID / UUID должно быть не менее 32 символов и должно оставаться в диапазоне ASCII, чтобы избежать проблем при их передаче.

Ответы [ 53 ]

36 голосов
/ 20 сентября 2008

Из технического блога Саги Шкеди :

function generateGuid() {
  var result, i, j;
  result = '';
  for(j=0; j<32; j++) {
    if( j == 8 || j == 12 || j == 16 || j == 20) 
      result = result + '-';
    i = Math.floor(Math.random()*16).toString(16).toUpperCase();
    result = result + i;
  }
  return result;
}

Существуют и другие методы, использующие элемент управления ActiveX, но держитесь подальше от них!

Редактировать: Я подумал, что стоит указать, что никакой генератор GUID не может гарантировать уникальные ключи (см. Статью википедии ). Всегда есть вероятность столкновения. GUID просто предлагает достаточно большой набор ключей, чтобы уменьшить количество столкновений почти до нуля.

33 голосов
/ 13 октября 2015

Вы можете использовать node-uuid (https://github.com/kelektiv/node-uuid)

Простая, быстрая генерация RFC4122 UUIDS.

Особенности:

  • Создание идентификаторов UUID RFC4122 версии 1 или версии 4
  • Запускается в node.js и браузерах.
  • Криптографически сильная случайная генерация # на поддерживающих платформах.
  • Небольшая площадь (Хотите что-нибудь поменьше? Проверьте это! )

Установка с использованием NPM:

npm install uuid

Или используя uuid через браузер:

Загрузить файл в формате Raw (uuid v1): https://raw.githubusercontent.com/kelektiv/node-uuid/master/v1.js Загрузить Raw File (uuid v4): https://raw.githubusercontent.com/kelektiv/node-uuid/master/v4.js


Хотите еще меньше? Проверьте это: https://gist.github.com/jed/982883


Использование:

// Generate a v1 UUID (time-based)
const uuidV1 = require('uuid/v1');
uuidV1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'

// Generate a v4 UUID (random)
const uuidV4 = require('uuid/v4');
uuidV4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'

// Generate a v5 UUID (namespace)
const uuidV5 = require('uuid/v5');

// ... using predefined DNS namespace (for domain names)
uuidV5('hello.example.com', v5.DNS)); // -> 'fdda765f-fc57-5604-a269-52a7df8164ec'

// ... using predefined URL namespace (for, well, URLs)
uuidV5('http://example.com/hello', v5.URL); // -> '3bbcee75-cecc-5b56-8031-b6641c1ed1f1'

// ... using a custom namespace
const MY_NAMESPACE = '(previously generated unique uuid string)';
uuidV5('hello', MY_NAMESPACE); // -> '90123e1c-7512-523e-bb28-76fab9f2f73d'

ES6:

import uuid from 'uuid/v4';
const id = uuid();
31 голосов
/ 20 сентября 2008

Веб-сервис будет полезен.

Быстрый поиск Google: http://www.hoskinson.net/GuidGenerator/

Не могу поручиться за эту реализацию, но SOMEONE должен опубликовать добросовестный генератор GUID.

С помощью такого веб-сервиса вы можете разработать веб-интерфейс REST, который использует веб-сервис GUID и передает его через AJAX в javascript в браузере.

31 голосов
/ 28 августа 2011
var uuid = function() {
    var buf = new Uint32Array(4);
    window.crypto.getRandomValues(buf);
    var idx = -1;
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        idx++;
        var r = (buf[idx>>3] >> ((idx%8)*4))&15;
        var v = c == 'x' ? r : (r&0x3|0x8);
        return v.toString(16);
    });
};

EDIT:

Пересмотрел мой проект, который использовал эту функцию и не любил многословие. - Но нужна была правильная случайность.

Версия, основанная на ответе Briguy37 и некоторых побитовых операторах для извлечения окон размером с полубайт из буфера.

Следует придерживаться схемы RFC Type 4 (случайная), поскольку в прошлый раз у меня были проблемы с анализом несовместимых UUID с UUID в Java.

29 голосов
/ 02 февраля 2013

Простой модуль JavaScript как комбинация лучших ответов в этой теме.

var crypto = window.crypto || window.msCrypto || null; // IE11 fix

var Guid = Guid || (function() {

  var EMPTY = '00000000-0000-0000-0000-000000000000';

  var _padLeft = function(paddingString, width, replacementChar) {
    return paddingString.length >= width ? paddingString : _padLeft(replacementChar + paddingString, width, replacementChar || ' ');
  };

  var _s4 = function(number) {
    var hexadecimalResult = number.toString(16);
    return _padLeft(hexadecimalResult, 4, '0');
  };

  var _cryptoGuid = function() {
    var buffer = new window.Uint16Array(8);
    window.crypto.getRandomValues(buffer);
    return [_s4(buffer[0]) + _s4(buffer[1]), _s4(buffer[2]), _s4(buffer[3]), _s4(buffer[4]), _s4(buffer[5]) + _s4(buffer[6]) + _s4(buffer[7])].join('-');
  };

  var _guid = function() {
    var currentDateMilliseconds = new Date().getTime();
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(currentChar) {
      var randomChar = (currentDateMilliseconds + Math.random() * 16) % 16 | 0;
      currentDateMilliseconds = Math.floor(currentDateMilliseconds / 16);
      return (currentChar === 'x' ? randomChar : (randomChar & 0x7 | 0x8)).toString(16);
    });
  };

  var create = function() {
    var hasCrypto = crypto != 'undefined' && crypto !== null,
      hasRandomValues = typeof(window.crypto.getRandomValues) != 'undefined';
    return (hasCrypto && hasRandomValues) ? _cryptoGuid() : _guid();
  };

  return {
    newGuid: create,
    empty: EMPTY
  };
})();

// DEMO: Create and show GUID
console.log(Guid.newGuid());

Использование:

Guid.newGuid ()

"c6c2d12f-d76b-5739-e551-07e6de5b0807"

Guid.empty

"00000000-0000-0000-0000-000000000000"

25 голосов
/ 20 сентября 2008

Из доброй старой википедии есть ссылка на реализацию UUID на JavaScript.

Это выглядит довольно элегантно, и, возможно, его можно улучшить, добавив хэш IP-адреса клиента. Возможно, этот хеш может быть вставлен в серверную часть HTML-документа для использования клиентским JavaScript.

ОБНОВЛЕНИЕ: на оригинальном сайте произошла случайная перестановка, вот обновленная версия

24 голосов
/ 22 июля 2014

Ну, у этого уже есть куча ответов, но, к сожалению, в этой группе нет "истинного" случайного числа. Приведенная ниже версия является адаптацией ответа broofa, но обновлена ​​и теперь включает в себя «истинную» случайную функцию, которая использует криптографические библиотеки, где это возможно, и функцию Alea () в качестве запасного варианта.

  Math.log2 = Math.log2 || function(n){ return Math.log(n) / Math.log(2); }
  Math.trueRandom = (function() {
  var crypt = window.crypto || window.msCrypto;

  if (crypt && crypt.getRandomValues) {
      // if we have a crypto library, use it
      var random = function(min, max) {
          var rval = 0;
          var range = max - min;
          if (range < 2) {
              return min;
          }

          var bits_needed = Math.ceil(Math.log2(range));
          if (bits_needed > 53) {
            throw new Exception("We cannot generate numbers larger than 53 bits.");
          }
          var bytes_needed = Math.ceil(bits_needed / 8);
          var mask = Math.pow(2, bits_needed) - 1;
          // 7776 -> (2^13 = 8192) -1 == 8191 or 0x00001111 11111111

          // Create byte array and fill with N random numbers
          var byteArray = new Uint8Array(bytes_needed);
          crypt.getRandomValues(byteArray);

          var p = (bytes_needed - 1) * 8;
          for(var i = 0; i < bytes_needed; i++ ) {
              rval += byteArray[i] * Math.pow(2, p);
              p -= 8;
          }

          // Use & to apply the mask and reduce the number of recursive lookups
          rval = rval & mask;

          if (rval >= range) {
              // Integer out of acceptable range
              return random(min, max);
          }
          // Return an integer that falls within the range
          return min + rval;
      }
      return function() {
          var r = random(0, 1000000000) / 1000000000;
          return r;
      };
  } else {
      // From http://baagoe.com/en/RandomMusings/javascript/
      // Johannes Baagøe <baagoe@baagoe.com>, 2010
      function Mash() {
          var n = 0xefc8249d;

          var mash = function(data) {
              data = data.toString();
              for (var i = 0; i < data.length; i++) {
                  n += data.charCodeAt(i);
                  var h = 0.02519603282416938 * n;
                  n = h >>> 0;
                  h -= n;
                  h *= n;
                  n = h >>> 0;
                  h -= n;
                  n += h * 0x100000000; // 2^32
              }
              return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
          };

          mash.version = 'Mash 0.9';
          return mash;
      }

      // From http://baagoe.com/en/RandomMusings/javascript/
      function Alea() {
          return (function(args) {
              // Johannes Baagøe <baagoe@baagoe.com>, 2010
              var s0 = 0;
              var s1 = 0;
              var s2 = 0;
              var c = 1;

              if (args.length == 0) {
                  args = [+new Date()];
              }
              var mash = Mash();
              s0 = mash(' ');
              s1 = mash(' ');
              s2 = mash(' ');

              for (var i = 0; i < args.length; i++) {
                  s0 -= mash(args[i]);
                  if (s0 < 0) {
                      s0 += 1;
                  }
                  s1 -= mash(args[i]);
                  if (s1 < 0) {
                      s1 += 1;
                  }
                  s2 -= mash(args[i]);
                  if (s2 < 0) {
                      s2 += 1;
                  }
              }
              mash = null;

              var random = function() {
                  var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
                  s0 = s1;
                  s1 = s2;
                  return s2 = t - (c = t | 0);
              };
              random.uint32 = function() {
                  return random() * 0x100000000; // 2^32
              };
              random.fract53 = function() {
                  return random() +
                      (random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
              };
              random.version = 'Alea 0.9';
              random.args = args;
              return random;

          }(Array.prototype.slice.call(arguments)));
      };
      return Alea();
  }
}());

Math.guid = function() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c)    {
      var r = Math.trueRandom() * 16 | 0,
          v = c == 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
  });
};
23 голосов
/ 24 августа 2009

Этот UUID версии 4 создания (созданный из псевдослучайных чисел):

function uuid()
{
   var chars = '0123456789abcdef'.split('');

   var uuid = [], rnd = Math.random, r;
   uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
   uuid[14] = '4'; // version 4

   for (var i = 0; i < 36; i++)
   {
      if (!uuid[i])
      {
         r = 0 | rnd()*16;

         uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf];
      }
   }

   return uuid.join('');
}

Вот пример сгенерированных UUID:

682db637-0f31-4847-9cdf-25ba9613a75c
97d19478-3ab2-4aa1-b8cc-a1c3540f54aa
2eed04c9-2692-456d-a0fd-51012f947136
23 голосов
/ 03 июля 2012

JavaScript-проект на GitHub - https://github.com/LiosK/UUID.js

UUID.js RFC-совместимый генератор UUID для JavaScript.

См. RFC 4122 http://www.ietf.org/rfc/rfc4122.txt.

Особенности Генерирует UUID, соответствующие RFC 4122.

UUID версии 4 (UUID из случайных чисел) и UUID версии 1 (основанные на времени UUID) доступны.

Объект UUID предоставляет различные возможности доступа к UUID, включая доступ к поля UUID.

Низкое временное разрешение JavaScript компенсируется случайным образом число.

16 голосов
/ 15 июля 2010
  // RFC 4122
  //
  // A UUID is 128 bits long
  //
  // String representation is five fields of 4, 2, 2, 2, and 6 bytes.
  // Fields represented as lowercase, zero-filled, hexadecimal strings, and
  // are separated by dash characters
  //
  // A version 4 UUID is generated by setting all but six bits to randomly
  // chosen values
  var uuid = [
    Math.random().toString(16).slice(2, 10),
    Math.random().toString(16).slice(2, 6),

    // Set the four most significant bits (bits 12 through 15) of the
    // time_hi_and_version field to the 4-bit version number from Section
    // 4.1.3
    (Math.random() * .0625 /* 0x.1 */ + .25 /* 0x.4 */).toString(16).slice(2, 6),

    // Set the two most significant bits (bits 6 and 7) of the
    // clock_seq_hi_and_reserved to zero and one, respectively
    (Math.random() * .25 /* 0x.4 */ + .5 /* 0x.8 */).toString(16).slice(2, 6),

    Math.random().toString(16).slice(2, 14)].join('-');
...