본문 바로가기
카테고리 없음

[SSAFY] 관통프로젝트 - 3 - 알고리즘 적용

by codeomni 2024. 10. 18.
반응형

비밀번호 해시 알고리즘 적용

1. 기존 상태

기존에는 비밀번호는 암호화를 적용하지 않는 raw 상태로 저장되어 있습니다. DB의 `members` 테이블을 SELECT로 조회를 하면 user_password에서 확인할 수 있습니다.

 


2. 적용하기

1) 의존성 추가

jBCrypt는 Java에서 BCrypt 해시 알고리즘을 구현한 라이브러리입니다. 해시함수를 사용해서 비밀번호를 암호화하고, 쉽게 복호화할 수 없게 설계되어 있습니다. 무작위 솔트(salt)와 반복적인 해시 처리를 통해서 무차별 대입 공격(Brute-force attack)을 방지할 수 있습니다.

<dependency>
    <groupId>org.mindrot</groupId>
    <artifactId>jbcrypt</artifactId>
    <version>0.4</version>
</dependency>

 

3) 비밀번호 저장 테이블 수정

비밀번호를 해싱하면 변환된 해시로 저장하기 때문에 비밀번호의 길이가 길어집니다. 따라서 데이터베이의 user_password의 길이도 변경되어야 합니다.

일반적으로 VARCHAR(60) 이상을 권장합니다.

ALTER TABLE members MODIFY user_password VARCHAR(60);

 

4)  유틸리티 클래스 구현

비밀번호를 해싱하고 검증하는 유틸리티 클래스를 구현합니다.

package com.ssafy.util;

import org.mindrot.jbcrypt.BCrypt;

public class PasswordUtil {

    // 비밀번호 해시 생성
    public static String hashPassword(String plainPassword) {
        return BCrypt.hashpw(plainPassword, BCrypt.gensalt());
    }

    // 비밀번호 검증
    public static boolean checkPassword(String plainPassword, String hashedPassword) {
        return BCrypt.checkpw(plainPassword, hashedPassword);
    }

}

 

5) 회원가입 시 비밀번호 암호화 저장

회원가입 시 입력된 비밀번호를 해싱해서 데이터베이스에 저장하도록 MemberControlle를 수정합니다.

MemberController에서 비밀번호를 해싱해서 서비스로 전달하도록 수정합니다.

// 비밀번호 해싱
String plainPassword = request.getParameter("userpwd");
String hashedPawword = PasswordUtil.hashPassword(plainPassword);

memberDto.setUserPwd(hashedPawword);

 

6) 로그인 시 비밀번호 검증

사용자가 로그인 시 입력된 비밀번호와 데이터베이스에 해시로 저장된 비밀번호를 비교하도록 MemberServiceImpl과 MemberServiceImpl을 수정합니다.

import com.ssafy.util.PasswordUtil;

// ...

@Override
public MemberDto loginMember(String userId, String userPwd) throws Exception {
    MemberDto memberDto = memberDao.getMemberById(userId);
    if (memberDto != null) {
        String hashedPassword = memberDto.getUserPwd();
        if (PasswordUtil.checkPassword(userPwd, hashedPassword)) {
            return memberDto;
        }
    }
    return null;
}

 

loginMember 메소드를 사용자 ID로만 조회하도록 변경하고, 비밀번호 검증은 서비스 계층에서 수행하도록 변경합니다.

@Override
public MemberDto getMemberById(String userId) throws SQLException {
	MemberDto memberDto = null;
	Connection conn = null;
	PreparedStatement pstmt = null;
    ResultSet rs = null;
	    
	try {
    	conn = dbUtil.getConnection();
	    StringBuilder sql = new StringBuilder();
	    sql.append("SELECT * FROM members WHERE user_id = ?");
	    pstmt = conn.prepareStatement(sql.toString());
	    pstmt.setString(1, userId);
	    rs = pstmt.executeQuery();
	    if (rs.next()) {
        	memberDto = new MemberDto();
	        memberDto.setUserId(rs.getString("user_id"));
	            
	        // 해시
	        // 해시된 비밀번호
	        memberDto.setUserPwd(rs.getString("user_password"));
	        memberDto.setUserName(rs.getString("user_name"));
	        memberDto.setEmailId(rs.getString("email_id"));
	        memberDto.setEmailDomain(rs.getString("email_domain"));
	        memberDto.setJoinDate(rs.getString("join_date"));
		}
    } finally {
		dbUtil.close(rs, pstmt, conn);
	}
	    
	return memberDto;
}

 

7) 구현 결과 확인

데이터베이스에서 해시로 비밀번호가 설정되어 있는지 확인합니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

댓글