public class Password {
    public static void main(String[] args) {
        int passLength = 10; // 패스워드 길이
        int passNumber = 20; // 생성할 패스워드 개수
        int[] password = new int[passLength];
        for (int i = 0; i < passNumber; i++) {
            int number = 0;
            int special = 0;
            int lower = 0;
            int upper = 0;
            for (int j = 0; j < password.length; j++) {
                int ranNum;
                ranNum = (int) ((Math.random() * 94) + 33);
                password[j] = ranNum;
                if (ranNum < 48) {
                    special = 1;
                } else if (ranNum < 58) {
                    number = 1;
                } else if (ranNum < 65) {
                    special = 1;
                } else if (ranNum < 91) {
                    upper = 1;
                } else if (ranNum < 97) {
                    special = 1;
                } else if (ranNum < 123) {
                    lower = 1;
                } else {
                    special = 1;
                }
            }
            if (number + special + lower + upper >= 3) {
                for (int n : password) {
                    System.out.print((char) n);
                }
                System.out.println();
            } else {
                i--;
            }
        }
    }
}


지난번에 올렸던 글에 댓글이 달려가지고... 퇴근하고 집에 와서 호기심에 한번 만들어 봤습니다. 비겁한 변명이지만 저는 개발자도 아니고 자바는 신입사원 교육 때 2주간 기초교육 받아본게 전부라서... 코드가 매우 허접합니다. 그래도 제가 이런 허접한 코드를 짜서 올리는 이유는, 개발자 분들의 황금같은 조언을 얻고자...

제가 이렇게 짜면서 궁금했던 부분은

1. 랜덤하게 뽑은 숫자가 ASCII 코드표의 특수문자, 숫자, 대문자, 소문자 중 어디에 속하는지를 검사하는 좀 더 세련된 방법이 없을까?

2. 최소 3가지 이상 종류가 조합되었는지 여부를 판단하는 좀 더 세련된 방법이 없을까?

아무튼 허접한 코드 봐주셔서 감사하고, 더 좋은 방법이 있다면 언제든지 조언해주시면 귀담아 듣겠습니다. 감사합니다.
신고
Share
  1. 지나가다
    2011.12.27 01:15 신고

    int i;
    int flag = 0; // 문자열에서 원하는 문자 포함시 1, 아니면 0
    char str[] = "He11o, W0rld!"; // 패스워드

    for (i=0; i<strlen(str); i++)
    if (0 <= str[i] && str[i] <= 100)
    {
    printf("문자열 포함");
    flag = 1;
    }
    else
    {
    printf("문자열을 포함하지 않음");
    flag = 0;
    exit(1);
    }

    이런 식으로 문자 코드에 해당하는 범위안에서 문자가 있는지 확인하는 코드를 알파벳, 숫자, 특수문자별로 작성해서 사용하세요.

    Java에서 문자열을 판별하는 함수를 제공한다면 그것 이용하시면 되구요.

  2. BlogIcon onmay
    2011.12.27 01:31 신고

    java로 쓴다면... (테스트는 안해봤음)
    private Boolean IsComplexPassword(String str) {
    Pattern p = Pattern.compile("/(?=^.{8,}$)((?=.*\\d)|(?=.*\\W+))(?![.\\n])(?=.*[A-Z])(?=.*[a-z]).*$/");
    Matcher m = p.matcher(str);
    return m.matches();
    }

  3. BlogIcon onmay
    2011.12.27 01:32 신고

    스눕씨 개발자 되시려고?^^;
    php로 쓰면... (테스트 완료)
    function IsComplexPassword($str) {
    if(!preg_match('/(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$/', $str))return false;
    return true;
    }

  4. 실용주의
    2011.12.28 04:05 신고

    문자열 검증은 정규식이 최고죠.. ^^*
    이미 좋은 예제를 주신 분이 계셔서 저는 pass~

  5. 재훈
    2011.12.28 14:07 신고

    안녕하세요. 평소에 포스트 잘 보고 있습니다.
    위에 댓글들에 나왔듯이 Regular Expression을 사용해서 검증하는 것이 가장 좋은 방법으로 생각됩니다.

  6. 용한
    2011.12.30 02:08 신고

    좋은 예제 감사 합니다.

    정규식은 체크라서.

    취지는 생성 인것 같은데요.

    뭘 그리 어렵게. 전 초보라서 ㅎㅎ..

    생성만 한다면

    랜덤으로 헥사값을 발생시켜서 만드는게 제일 좋지 않을까 생각 되네요.

    srand();
    $challenge = "";
    for ($i = 0; $i < 20; $i++) {
    $challenge .= dechex(rand(0, 15));
    }

  7. BlogIcon onmay
    2012.08.18 00:47 신고

    생각나서 만들어 봄.
    <!DOCTYPE html>
    <meta charset='UTF-8'>
    <title>복잡한 패스워드 생성기</title>
    <h1>복잡한 패스워드 생성기</h1>
    <p>대문자 2개 + 소문자 2개 + 숫자 2개 + 특수문자 2개</p>
    <?php
    $uppers = str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ');
    $lowers = str_shuffle('abcdefghijklmnopqrstuvwxyz');
    $numbers = str_shuffle('1234567890');
    $specials = str_shuffle('!@#$%^&*()');
    $complex_password = substr($uppers,-2).substr($lowers,-2).substr($numbers,-2).substr($specials,-2);
    $more_complex_password = str_shuffle($complex_password);
    echo "복잡한 패스워드: <input type='text' value='$complex_password'><br>";
    echo "더 복잡한 패스워드: <input type='text' value='$more_complex_password'><br>";
    ?>
    http://jmnote.com/wiki/복잡한_패스워드_생성기

  8. 아야노비
    2014.04.09 18:29 신고

    …오랜된 글이네요 보통은 랜덤을 뽑아놓고 다시 하려고 하는데
    그렇게 하기보다는 미리 문자열들을 준비시켜놓고
    섞는방법을 추천드려요

    옐르들어서 로또 번호 45개중 7개를 뽑는다고 한다면
    보통 프로그램을 하면 공 랜덤 1개뽑고 그다음공 또 뽑아서 중복인지 검사하고 …
    그런방식이 아니라


    공을 45개 미리 뽑아 놓고 마구잡이로 섞은다음 배열 첫번재 부터 7번재 순에 잇는 공을 배는것처럼요

  9. ㅇㅇ
    2014.08.05 11:01 신고

    Math.random은 Linear Congruential Generator를 사용해서 난수를 생성합니다. LCG는 몇 번의 결과를 살펴보면 예측이 가능하구요. (Mersenne Twister도 예측 가능합니다)
    비밀번호에 사용할 거라면 예측이 어려운 SecureRandom을 사용하는 게 좋습니다. 리눅스 환경에서 SecureRandom은 디스크, 키보드 등의 디바이스의 노이즈를 이용해서 난수를 생성하기 때문에 예측이 매우 어렵다고 합니다.

  10. 칡흙
    2015.12.18 14:02 신고

    @Test
    public void testisComplexPassword() {
    isComplexPassword("A-1a");
    }

    public void isComplexPassword(String passwd) {
    String numberCheck = passwd.replaceAll("[0-9]", ""); // 숫자체크
    String lowerCheck = numberCheck.replaceAll("[a-z]", ""); // 소문자체크
    String upperCheck = lowerCheck.replaceAll("[A-Z]", ""); // 대문자체크

    assertFalse(numberCheck.length()==passwd.length(), "숫자가 없습니다");
    assertFalse(lowerCheck.length()==numberCheck.length(), "소문자가 없습니다");
    assertFalse(upperCheck.length()==lowerCheck.length(), "대문자가 없습니다");

    // 숫자, 소문자, 대문자가 아닐경우 특수문자로 생각한다면...
    assertFalse(upperCheck.length()==0, "특수문자가 없습니다.");
    }