본문 바로가기

프로젝트/라꾸라꾸 프로젝트

[보안] 패스워드 보안 지침

개발할 때 사용자의 패스워드를 어떻게 처리해야 할 지 고민이 되었다. 많은 서비스에서 영문, 숫자, 특수 기호를 조합하라는 조건을 본 것 같다.

더 구체적으로 직접 서비스를 개발할 때 어떤 조건을 주어야 하고 어떤 방식으로 저장해야할 지 고민이 되어(비밀번호를 그대로 저장하면 개발자들이 뭔짓을 할 수도 있지 않는가!) KISA의 안내 지침을 찾아서 작성해보았다. 

 

KISA에서 제공하는 "패스워드 선택 및 이용 안내서"에 따르면 

 

1) 초기 패스워드, 패스워드 분실 등의 이유로 이용자에게 제공하기 위해 생성된 패스워드는 최소 6자 이상이어야하며

안전하게 생성된 난수여야 한다. 

 

-> 라꾸라꾸 프로젝트의 경우 다음과 같이 난수를 생성하여 사용자의 이메일로 전송하는 방법을 이용했다. 

public String getTempPwd() {
		char[] charSet = new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
				'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
				'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};

		String pwd = "";

		/* 문자 배열 길이의 값을 랜덤으로 10개를 뽑아 조합 */
		int idx = 0;
		for(int i = 0; i < 10; i++){
			idx = (int) (charSet.length * Math.random());
			pwd += charSet[idx];
		}

		return pwd;
	}

 

2) 패스워드를 최소 8자 이상으로 요구해야 하며, 영문, 숫자, 특수 기호를 조합하여 사용할 수 있도록 허용해야 한다. 

 

-> 라꾸라꾸 프로젝트의 경우 프론트엔드 단에서 해당 조건이 만족하는지 바로 확인하여 오류 메시지를 띄웠다. 또한, 백엔드에서도 한 번 더 조건이 만족하는지 체크하면 좋다고 하여 @valid 어노테이션을 이용하여 조건을 만족하지 않으면 json으로 에러 메시지를 보냈다. 


@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class SignupReqDto { // 가입할 때 유저가 입력해야 하는 정보들
	@NotBlank
	@Email(message = "이메일 형식이 아닙니다.")
	private String email;
    
    
	@NotBlank
	@Length(min = 2, max = 16)
	@Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[!.?,])[A-Za-z\\d!.?,]{2,16}$",
			message = "16자 이내의 영문자 및 숫자와 ?,!,., , 특수문자로 입력해주세요.")
	private String password;
    
    
	@NotBlank
	private String nickname;

....

}
//서비스 단에서 회원가입 메소드이다. 
    
    @PostMapping("/signup")
	public ResponseEntity<String> signup(@Valid @RequestBody SignupReqDto reqDto) {
		usersService.signup(reqDto);
		return ResponseEntity.ok(SIGNUP_SUCCESS);
	}

 

3) 반복적으로 잘못된 패스워드를 입력할 경우, 입력 횟수를 제한하는 시스템을 구현해야 합니다. 

 

4) 이용자가 패스워드를 변경하고자 할 때 관리자는 패스워드가 안전한지 홗인하여 이용자에게 알리고 안전하지 않을 경우 다른 값을 요구하는 시스템을 구현해야 합니다. 

 

5) 패스워드를 여러 번의 일방향 해시함수를 사용하고 패스워드와 함께 사용하는 솔트(salt)는 안전하게 저장해야 합니다.