(최종) 시리얼번호 생성 함수
사용상에는 아무런 제한이 없습니다.
출처를 밝히고 퍼가는 것도 아무런 제한이 없습니다.
단, 교육(강좌)의 내용이나 출판(책)의 내용으로 포함되거나 인용 될수 없습니다.
몇가지 내용이 변경되었습니다.
1. 베이스가 되는 숫자 문자열을 36자로 유니크하게 생성합니다.
2. 유니크한 숫자에 랜덤한 5자리 소수 가 곱해집니다.
3. 자리수의 한도가 생겻습니다. 숫자형은 36자리 까지, 믹스형은 24자리까지 입니다.
4. 12자리 미만은 대량 생성시 중복이나 연번 발생 할수 있습니다. 생성시 중복체크는 필수 입니다.
[사용예시]
보통 이런 시리얼 번호는
미리 100 만건 정도를 데이타베이스에 생성해놓고
사용자 발급 요청이 있을시 사용되지 않은것중 하나를 발급합니다.
이미 생성할때 랜덤하게 되었기 때문에 발급되지 않은 것중 하나를 순차적으로 뽑아서 발급합니다.
발급후 발급 으로 상태를 변경합니다.
시리얼 사용 입력을 받을 때는 아이피당으로 하루 실패 5회 이상을 넘지 못하게 합니다.
악의적인 프로그램을 사용할수 있는 경우 때문입니다.
입력받은 시리얼은 데이타베이스에서 비교하여
존재하는 시리얼인지
발급되었던 시리얼인지
사용되었던 시리얼인지
체크 한 연후에 아무 이상이 없을 경우 사용 으로 상태를 변경하고
사용할수 있는 서비스 정보를 업데이트 합니다.
<?php
//지정된 자릿수의 랜덤한 숫자를 반환합니다. 최대 10까지 가능합니다. 4 이면 1000 에서 9999 사이의 랜덤 숫자
function get_rand_number($len=4) {
$len = abs((int)$len);
if ($len < 1) $len = 1;
else if ($len > 10) $len = 10;
return rand(pow(10, $len - 1), (pow(10, $len) - 1));
}
//넘어온 세자리수를 36진수로 변환해서 반환합니다. preg_match_callback 을 통해서만 사용됩니다.
function get_simple_36($m){
$str = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$div = floor($m[0] / 36);
$rest = $m[0] % 36;
return $str[$div] . $str[$rest];
}
//지정된 자리수에 존재하는 소수 전체를 배열로 반환합니다. max len = 5
function get_simple_prime_number($len=5){
$len = abs((int)$len);
if ($len < 1) $len = 1;
else if ($len > 5) $len = 5;
$prime_1 = Array(1, 2, 3, 5, 7);
if ($len == 1) return $prime_1;
$start = pow(10, ($len - 1)) + 1;//101
$end = pow(10, $len) - 1;//999
$prime = $prime_1;
unset($prime[0]);//1제거
unset($prime[1]);//2제거
$array = Array();
for($i = 11; $i <= $end; $i+=2){//10보다 큰 소수에는 짝수가 없다.
function get_simple_prime_number($len=5){
$len = abs((int)$len);
if ($len < 1) $len = 1;
else if ($len > 5) $len = 5;
$prime_1 = Array(1, 2, 3, 5, 7);
if ($len == 1) return $prime_1;
$start = pow(10, ($len - 1)) + 1;//101
$end = pow(10, $len) - 1;//999
$prime = $prime_1;
unset($prime[0]);//1제거
unset($prime[1]);//2제거
$array = Array();
for($i = 11; $i <= $end; $i+=2){//10보다 큰 소수에는 짝수가 없다.
$max = floor(sqrt($i));
foreach($prime as $j) {
if ($j > $max) break;
if ($i % $j == 0) continue 2;
}
$prime[] = $i;
if ($i >= $start) $array[] = $i;
}
return $array;
}
foreach($prime as $j) {
if ($j > $max) break;
if ($i % $j == 0) continue 2;
}
$prime[] = $i;
if ($i >= $start) $array[] = $i;
}
return $array;
}
//지정된 자릿수의 숫자로된 시리얼을 반환합니다. - 를 포함하고 싶지 않을때는 $cut 이 $len 보다 크거나 같으면 됩니다. max len = 36
function get_serial($len=16, $cut=4, $hipen='-'){
$len = abs((int)$len);
if ($len < 1) $len = 16;
else if ($len > 36) $len = 36;
$cut = abs((int)$cut);
if ($cut < 1) $cut = 4;
else if ($cut > $len) $cut = $len;
list($usec, $sec) = explode(' ', microtime());
$base_number = (string)$sec . str_replace('0.', '', (string)$usec);
$base_number .= (string)get_rand_number(10) . (string)get_rand_number(8);//36자리 유니크한 숫자 문자열
$base_number = (string)$sec . str_replace('0.', '', (string)$usec);
$base_number .= (string)get_rand_number(10) . (string)get_rand_number(8);//36자리 유니크한 숫자 문자열
$prime = get_simple_prime_number(5);//5자리 소수 배열
shuffle($prime);
$prime = $prime[0];//랜덤한 5자리 소수
$serial = bcmul(substr($base_number, 0, $len), $prime);
$serial_length = strlen($serial);
$sub = $len - $serial_length;
if ($sub > 0) $serial .= (string)get_rand_number($sub);
else if ($sub < 0) $serial = substr($serial, 0, $len);
return preg_replace("`(.{" . $cut . "})`", "$1" . $hipen, $serial, floor(($len-1) / $cut));
}
//지정된 자릿수의 숫자와 영문으로된 시리얼을 반환합니다. - 를 포함하고 싶지 않을때는 $cut 이 $len 보다 크거나 같으면 됩니다. max len = 24
function get_serial_mix($len=16, $cut=4, $hipen='-'){
$len = abs((int)$len);
if ($len < 1) $len = 16;
else if ($len > 24) $len = 24;
$cut = abs((int)$cut);
if ($cut < 1) $cut = 4;
else if ($cut > $len) $cut = $len;
$len2 = (int)($len * 3 / 2);
if ($len2 % 2 == 1) $len2 += 1;
$serial = get_serial($len2, $len2, $hipen);
$serial = substr(preg_replace_callback("`.{3}`", "get_simple_36", $serial), 0, $len);
return preg_replace("`(.{" . $cut . "})`", "$1" . $hipen, $serial, floor(($len-1) / $cut));
}
echo get_serial_mix(16, 4, '-');
?>
댓글 14개
Terrorboy
13년 전
추천합니다.!!
13년 전
감사합니다. ^^
혹시 기존의 랜덤 숫자 대신 소수를 사용하신 이유을 여쭤봐도 될까요?
그냥 생각에, 랜덤 숫자보다 소수의 가지수가 훨씬 적어서 결과적으로 나올 수 있는 숫자의 종류도 적어질것 같아서요. ^^'
혹시 기존의 랜덤 숫자 대신 소수를 사용하신 이유을 여쭤봐도 될까요?
그냥 생각에, 랜덤 숫자보다 소수의 가지수가 훨씬 적어서 결과적으로 나올 수 있는 숫자의 종류도 적어질것 같아서요. ^^'
13년 전
네에 그렇게 한이유는
이전방법이든 현재방법이든
일정 자릿수 이상에선 동시에 생성시 중복은 없습니다.
그렇지만, 일정시간이 흐룬후 다시 생성햇을때
이전 생성된 번호가 미약하나마 나올수 있어서(곱하기 때문에)
소수를 사용하게 되었습니다.
소수는 더 나누어질수 없는 수이기 때문에
앞에 시간이 정확히 일치 하지 않으면 완전한 동일한 수는 나올 확률이 아예 없습니다.
그런데 시간은 뒤로 흐르니
언제 어느시점에 해도 일정 자리수 이상에선 절대 중복이 나올수 없습니다.
이전방법이든 현재방법이든
일정 자릿수 이상에선 동시에 생성시 중복은 없습니다.
그렇지만, 일정시간이 흐룬후 다시 생성햇을때
이전 생성된 번호가 미약하나마 나올수 있어서(곱하기 때문에)
소수를 사용하게 되었습니다.
소수는 더 나누어질수 없는 수이기 때문에
앞에 시간이 정확히 일치 하지 않으면 완전한 동일한 수는 나올 확률이 아예 없습니다.
그런데 시간은 뒤로 흐르니
언제 어느시점에 해도 일정 자리수 이상에선 절대 중복이 나올수 없습니다.
13년 전
설명 감사드립니다. ^^
난수 생성 방법중에도 소수를 이용하는 알고리즘이 있는데,
비슷한 원리가 아닐까 생각합니다.
이 정도의 코드라면, 거의 완벽에 가까운 시리얼 키 생성함수가 아닐까 생각되네요.
정말 많은 공부되었습니다. 이런 기회를 주셔서 너무 고맙습니다. ^^*
난수 생성 방법중에도 소수를 이용하는 알고리즘이 있는데,
비슷한 원리가 아닐까 생각합니다.
이 정도의 코드라면, 거의 완벽에 가까운 시리얼 키 생성함수가 아닐까 생각되네요.
정말 많은 공부되었습니다. 이런 기회를 주셔서 너무 고맙습니다. ^^*
13년 전
별말씀을요
잘 보아 주셔서 고맙습니다.
잘 보아 주셔서 고맙습니다.
똥싼너구리
13년 전
와우 점점 디테일해지는군용!!
13년 전
list($usec, $sec) = explode(' ', microtime());
$base_number = str_repeat((string)$sec, 2);
$base_number .= str_repeat(str_replace('0.', '', (string)$usec), 2);//36자리 유니크한 숫자 문자열
이부분은
list($usec, $sec) = explode(' ', microtime());
$base_number = (string)$sec . str_replace('0.', '', (string)$usec);
$base_number .= (string)get_rand_number(10) . (string)get_rand_number(8);//36자리 유니크한 숫자 문자열
이게 맞는거 같습니다.
$base_number = str_repeat((string)$sec, 2);
$base_number .= str_repeat(str_replace('0.', '', (string)$usec), 2);//36자리 유니크한 숫자 문자열
이부분은
list($usec, $sec) = explode(' ', microtime());
$base_number = (string)$sec . str_replace('0.', '', (string)$usec);
$base_number .= (string)get_rand_number(10) . (string)get_rand_number(8);//36자리 유니크한 숫자 문자열
이게 맞는거 같습니다.
13년 전
동시에 생성시 완벽한 중복을 피하기 위해서는
자릿수에 맞게 마이크로 타임이 항상 달라질수 있도록
usleep 을 적절히 사용해야 합니다.
예를들면
16자리 숫자 시리얼을 생성하고자 할때
while(1) {
get_serial(16, 4, '-');
usleep(10);//십만분의 1초 쉼
}
자릿수에 맞게 마이크로 타임이 항상 달라질수 있도록
usleep 을 적절히 사용해야 합니다.
예를들면
16자리 숫자 시리얼을 생성하고자 할때
while(1) {
get_serial(16, 4, '-');
usleep(10);//십만분의 1초 쉼
}
13년 전
그런데.... 내부에서 소수 구하는 부분에서
0.6초 대의 시간이 발생하므로
안넣어도 상관은 없을거 같기도 합니다.
0.6초 대의 시간이 발생하므로
안넣어도 상관은 없을거 같기도 합니다.
13년 전
아래글에도 댓글을 남겼는데,
pow 계산부분을 $prime 루프 밖으로 빼면 속도에 도움이 되는 것 같습니다. ^^
pow 계산부분을 $prime 루프 밖으로 빼면 속도에 도움이 되는 것 같습니다. ^^
13년 전
좋은 지적입니다.
요샌 집중력이 떨어져서 그런지
하나 적용하면 하나 빼먹고 그러네요.
요샌 집중력이 떨어져서 그런지
하나 적용하면 하나 빼먹고 그러네요.
13년 전
추천합니다.!!!
13년 전
네에 고맙습니다.
takumi22
12년 전
유용하게 사용할수 있을것 같습니다 감사합니다
게시글 목록
| 번호 | 제목 |
|---|---|
| 17559 |
Linux
주로 사용하는 리눅스 설치 방법?
5
|
| 17555 | |
| 17553 |
PHP
탭만드는거 질문입니다.
1
|
| 24398 | |
| 17550 |
MySQL
단순 텍스트파일 DB화 분류 방법
2
|
| 17547 |
jQuery
초심자용 jQuery 심플 트리 구조 예제
2
|
| 17540 |
PHP
PHP 내장 함수 모음
6
|
| 4284 | |
| 4279 | |
| 17538 |
MySQL
select 질문좀 굽신굽신
1
|
| 17535 | |
| 17533 | |
| 30392 | |
| 17532 |
정규표현식
정규식 일반전화 유효성 체크 예제
|
| 17531 |
정규표현식
정규식 휴대폰 유효성 체크 예제
|
| 17521 |
JavaScript
탑메뉴 부분만 깔끔하게 추출 가능한 고수님들께 부탁드립니다.
9
|
| 17513 |
jQuery
jQuery 책추천좀~
7
|
| 17512 |
기타
첨부파일이 안받다져요
|
| 30390 |
HTML
브라우저별 개별 css 적용
1
|
| 17510 |
node.js
node.js 0.8.0 release..
1
|
| 17507 |
기타
게임홈페이지제작./
2
|
| 17497 |
기타
아..활동지수...
9
|
| 17495 |
정규표현식
정규식 질문입니다
1
|
| 17492 |
JavaScript
이거 유게로 가야할지 여기에 올려야 할지 좀 혼동이 있는데...
2
|
| 30387 | |
| 17489 |
MySQL
서버이전 sql DB복구법
2
|
| 17487 | |
| 30385 | |
| 17485 | |
| 4267 | |
| 17483 |
JavaScript
슬라이드 실시간 챠트 등 스크립트 입니다.
1
|
| 17480 | |
| 17478 | |
| 17476 | |
| 17453 |
JavaScript
쿠키 질문합니다...
22
|
| 17451 |
Flash
플래시 글자수정질문드려요
1
|
| 17447 |
기타
tcp view
3
|
| 17436 |
JavaScript
자바스크립트 for문 숫자 더하기 질문
10
|
| 17434 |
JavaScript
전에 후라보노보노님을 괴롭히던 문제
1
|
| 17433 |
JavaScript
안녕하세요 처음 시작해보려고하는데요.
|
| 17430 | |
| 17429 | |
| 30380 | |
| 17423 | |
| 17422 |
PHP
템플릿엔진을 쓰는게 좋을까..
|
| 26365 | |
| 17419 | |
| 30379 |
HTML
주소 검색 소스~ 부탁드려요 ^^
|
| 17416 |
Linux
tcpd파일 관련 문의
2
|
| 17412 | |
| 17407 |
jQuery
jQuery chm 파일
4
|
| 30373 |
HTML
CSS 게시판 위치별 제어
5
|
| 17394 | |
| 17392 |
MySQL
고수님 봐주세요~
1
|
| 17389 | |
| 17385 | |
| 17384 | |
| 17381 | |
| 17380 |
Flash
플래시 제작 의뢰합니다 도와주세요.
|
| 17376 |
JavaScript
레이어 팝업창뛰우는거 도움받고자합니다. ㅜㅜ
3
|
| 17375 | |
| 17374 |
jQuery
^^
|
| 17372 |
PHP
세션에 대해 질문합니다.
1
|
| 17365 | |
| 30370 |
HTML
홈페이지 카테고리 수정 도움 요청
2
|
| 30366 | |
| 17362 |
jQuery
브라우저 버튼 고정시키기
2
|
| 17359 |
JavaScript
자바스크립트 배열 + php 처리.. 고수님들. 도움을 청합니다. ㅠ
2
|
| 17357 | |
| 17356 | |
| 17353 |
정규표현식
전화번호 "-" 구분자 넣기
2
|
| 17350 |
JavaScript
로그인하지 않고는 신청을 못하도록 하려면 어찌해야할까요? 그리고
2
|
| 17346 |
Linux
.tar 파일 질문입니다
3
|
| 30364 | |
| 17342 | |
| 4261 | |
| 17339 |
PHP
절대경로 질문!!
2
|
| 17336 | |
| 17332 | |
| 17330 | |
| 4243 | |
| 17328 | |
| 17325 | |
| 17321 | |
| 4242 | |
| 17317 |
Mobile
겔럭시노트 랙걸리는현상
3
|
| 17312 | |
| 17305 | |
| 4234 | |
| 17295 | |
| 4231 | |
| 24392 | |
| 17292 | |
| 17288 | |
| 17287 | |
| 17285 |
JavaScript
자바스크립트 오류인데요^^ 도와주실분^^
1
|
| 17283 | |
| 17275 |
jQuery
서랍형 아코디언 롤링배너 입니다.
7
|
| 26360 |
기획서
파일정의서 입니다.
4
|
| 26347 |
댓글 작성
댓글을 작성하시려면 로그인이 필요합니다.
로그인하기