문제

특히 PHP에서 항상 고유 키를 얻을 수 있는 방법을 찾고 있습니다.

나는 다음을 수행했습니다.

strtolower(substr(crypt(time()), 0, 7));

그러나 나는 가끔 중복된 키를 갖게 되는 것을 발견했습니다(드물지만 충분히 자주).

나는 또한 다음을 생각했습니다.

strtolower(substr(crypt(uniqid(rand(), true)), 0, 7));

그러나 PHP 웹 사이트에 따르면 uniqid()는 동일한 마이크로초 내에 uniqid()가 두 번 호출되면 동일한 키를 생성할 수 있습니다.나는 rand()를 추가하는 것이 거의 불가능하다고 생각하지만 여전히 가능합니다.

위에서 언급한 줄 다음에는 L, O 등의 문자도 제거하여 사용자에게 혼란을 주지 않습니다.이는 중복 원인의 일부일 수 있지만 여전히 필요합니다.

제가 생각하는 한 가지 옵션은 키를 생성하는 웹사이트를 만들고 이를 데이터베이스에 저장하여 완전히 고유한지 확인하는 것입니다.

다른 생각은 없나요?일종의 API가 있거나 키를 반환하는 이미 이 작업을 수행하는 웹사이트가 있습니까?나는 찾았다 http://userident.com 하지만 키가 완전히 고유한지는 잘 모르겠습니다.

사용자 입력 없이 백그라운드에서 실행되어야 합니다.

도움이 되었습니까?

해결책

고유한 값을 생성하는 방법은 비밀번호, 사용자 ID 등 3가지뿐입니다.

  1. 효과적인 GUID 생성기를 사용하세요. 이는 길고 축소할 수 없습니다.부분만 사용하는 경우 당신은 실패.
  2. 숫자의 적어도 일부는 단일 시퀀스에서 순차적으로 생성됩니다.보풀이나 인코딩을 추가하여 덜 순차적으로 보이도록 할 수 있습니다.장점은 짧게 시작한다는 것이고 단점은 단일 소스가 필요하다는 것입니다.단일 소스 제한에 대한 해결 방법은 번호가 매겨진 소스를 갖는 것입니다. 따라서 [소스 #] + [seq #]을 포함하면 각 소스가 자체 시퀀스를 생성할 수 있습니다.
  3. 다른 방법을 통해 생성한 다음 이전에 생성된 값의 단일 기록과 비교하여 확인합니다.

다른 방법은 보장되지 않습니다.기본적으로 이진수(컴퓨터)를 생성하지만 이를 16진수, 10진수, Base64 또는 단어 목록으로 인코딩할 수 있다는 점을 명심하세요.용도에 맞는 인코딩을 선택하세요.일반적으로 사용자가 입력한 데이터의 경우 Base32의 변형을 원합니다(암시한 것임).

GUID에 대한 참고 사항:그것들은 길이와 그것을 생성하는 데 사용된 방법으로부터 독창성의 힘을 얻습니다. 128비트 미만은 안전하지 않습니다. 난수 생성 외에도 GUID를 더욱 고유하게 만드는 특성이 있습니다.그것들은 단지 실질적으로 독특할 뿐이지 완전히 독특하지는 않다는 점을 명심하십시오.복제는 가능하지만 사실상 불가능합니다.

GUID에 대한 업데이트된 참고 사항:이 글을 쓴 이후로 나는 많은 GUID 생성기가 암호화된 보안 난수 생성기를 사용한다는 것을 알게 되었습니다(생성된 다음 숫자를 예측하기 어렵거나 불가능하며 반복될 가능성이 없음).실제로는 5가지가 있습니다 UUID 알고리즘.알고리즘 4는 Microsoft가 현재 Windows GUID 생성 API에 사용하는 것입니다.ㅏ GUID Microsoft의 UUID 표준 구현입니다.

업데이트:7~16자를 원하는 경우 방법 2 또는 3을 사용해야 합니다.

결론:솔직히 완전히 독특한 것은 없습니다.순차 생성기를 사용하더라도 결국에는 우주의 모든 원자를 사용하여 저장 공간이 부족하여 스스로 루프백하고 반복하게 됩니다.당신의 유일한 희망은 그 지점에 도달하기 전에 우주가 열사멸하는 것입니다.

최고의 난수 생성기라도 생성 중인 난수의 전체 크기와 동일하게 반복될 가능성이 있습니다.예를 들어 1/4을 예로 들어 보겠습니다.이는 완전한 무작위 비트 생성기이며 반복 확률은 2분의 1입니다.

따라서 모든 것이 고유성의 한계점에 도달합니다.시퀀스를 사용한 다음 이를 base32로 인코딩하면 1,099,511,627,776개의 숫자에 대해 8자리에서 100% 고유성을 가질 수 있습니다.과거 번호 목록을 확인하지 않는 다른 방법은 고유하지 않을 확률이 n/1,099,511,627,776(여기서 n=생성된 이전 번호 수)과 같습니다.

다른 팁

어떤 알고리즘이라도 중복이 발생합니다.

그러므로 기존 알고리즘*을 사용하여 단순히 중복 항목을 확인하는 것이 좋습니다.

*약간 추가:만약에 uniqid() 시간에 따라 고유하지 않을 수 있으며, 호출할 때마다 증가하는 전역 카운터도 포함됩니다.그렇게 하면 같은 마이크로초에도 뭔가가 달라집니다.

코드를 작성하지 않으면 내 논리는 다음과 같습니다.

원하는 허용 가능한 문자로 임의의 문자열을 생성하십시오.
그런 다음 날짜 스탬프의 절반(일부 초 및 전부)을 앞쪽에 추가하고 나머지 절반은 끝 부분(또는 원하는 경우 중간)에 추가합니다.

계속 졸리세요!
시간

원래 방법을 사용하지만 비밀번호 앞에 사용자 이름이나 이메일 주소를 추가하는 경우 각 사용자가 1개의 비밀번호만 가질 수 있다면 비밀번호는 항상 고유합니다.

동일한 문제를 다루는 다음 기사에 관심이 있을 수 있습니다. GUID는 전역적으로 고유하지만 GUID의 하위 문자열은 그렇지 않습니다..

이 알고리즘의 목표는 시간과 위치의 조합(상대성 이론 전문가를 위한 "시공간 좌표")을 고유성 키로 사용하는 것입니다.그러나 시간 유지는 완벽하지 않습니다. 따라서 예를 들어 두 개의 GUID가 동일한 시스템에서 빠르게 연속해서 생성되어 시간이 너무 가까워서 타임스탬프가 동일할 가능성이 있습니다.이것이 바로 uniquifier가 들어오는 곳입니다.

나는 보통 다음과 같이 한다:

$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));
}

이론적으로 허점이 있다고 생각하지만 복제 문제는 한번도 겪어본 적이 없습니다.저는 보통 임시 비밀번호(예: 비밀번호 재설정 후)에 이 기능을 사용하는데, 그 용도로는 충분합니다.

Frank Kreuger가 언급했듯이 GUID 생성기를 사용하십시오.

좋다 이 하나

비밀번호가 왜 고유해야 하는지 아직도 모르겠습니다.두 명의 사용자가 동일한 비밀번호를 사용하는 경우 단점은 무엇입니까?

이는 고유 식별자뿐만 아니라 사용자 ID와 연결된 비밀번호에 대해 이야기하고 있다고 가정합니다.만약에 그건 당신이 찾고 있는 것이 무엇인지, 왜 GUID를 사용하지 않습니까?

Steve Gibson의 최고 보안 암호 생성기 구현에 관심이 있으실 수도 있습니다(출처는 없지만 작동 방식에 대한 자세한 설명이 있음). https://www.grc.com/passwords.htm.

이 사이트는 64자의 거대한 비밀번호를 생성하지만 완전히 무작위이기 때문에 덜 안전하지만 "가능한 무작위" 비밀번호를 위해 처음 8자(또는 그 이상)를 쉽게 사용할 수 있습니다.

편집하다:이후 답변에서 비밀번호보다 GUID와 같은 것이 더 필요하다는 것을 알았으므로 아마도 원하는 것이 아닐 것입니다 ...

귀하의 문제 중 일부는 귀하가 두 가지 용도로 단일 기능을 사용하려고 한다는 것입니다...비밀번호 및 transaction_id

이는 실제로 서로 다른 두 가지 문제 영역이므로 함께 해결하려고 시도하는 것은 실제로 최선이 아닙니다.

나는 최근에 빠르고 간단한 임의의 고유 키를 원했기 때문에 다음을 수행했습니다.

$ukey = dechex(time()) . crypt( time() . md5(microtime() + mt_rand(0, 100000)) ); 

그래서 기본적으로 Unix 시간을 초 단위로 얻고 시간 + 난수에서 생성된 임의의 md5 문자열을 추가합니다.최고는 아니지만 빈도가 낮은 요청의 경우 꽤 좋습니다.빠르고 작동합니다.

수천 개의 키를 생성한 다음 반복을 찾는 테스트를 했는데 초당 약 800개의 키가 있어서 반복이 없었으므로 나쁘지 않습니다.나는 그것이 전적으로 mt_rand()에 달려 있다고 생각합니다.

분당 약 1000개의 설문조사 제출률을 얻는 설문조사 추적기에 사용합니다.그래서 지금은 (손가락을 교차하여) 중복된 항목이 없습니다.물론, 비율은 일정하지 않습니다(하루 중 특정 시간에 제출을 받습니다). 따라서 이것이 실패 방지도 아니고 최선의 해결책도 아닙니다.팁은 키의 일부로 증분 값을 사용하고 있습니다(제 경우에는 time()을 사용했지만 더 좋을 수도 있습니다).

고유한 값을 생성하는 것과 별로 관련이 없는 암호화 부분을 처리하기 위해 나는 일반적으로 다음을 사용합니다.

function GetUniqueValue()
{
   static $counter = 0; //initalized only 1st time function is called
   return strtr(microtime(), array('.' => '', ' ' => '')) . $counter++;
}

동일한 프로세스에서 호출되면 $counter가 증가하므로 값은 동일한 프로세스에서 항상 고유합니다.

다른 프로세스에서 호출될 때 동일한 값으로 2개의 microtime() 호출을 얻는 것은 정말 운이 좋지 않을 것입니다. microtime() 호출은 일반적으로 동일한 스크립트에서 호출될 때에도 다른 값을 갖는다고 생각하십시오.

나는 일반적으로 임의의 하위 문자열(사용자 편의를 위해 8에서 32 사이의 문자 수를 무작위로 지정) 또는 내가 얻은 일부 값의 MD5, 시간 또는 일부 조합을 수행합니다.더 많은 임의성을 위해 나는 값(예: 성)의 MD5를 시간과 연결하고 다시 MD5를 연결한 다음 임의의 하위 문자열을 가져옵니다.그래요 당신 ~할 수 있었다 동일한 비밀번호를 얻을 수 있지만 그럴 가능성은 전혀 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top