본문 바로가기
Spring & Spring Boot

Springboot & Vue3.js - 비밀번호 암호화 - BcryptPasswordEncoder

by 지민재 2023. 1. 11.
반응형
SMALL
개요

 

BcryptPasswordEncoderPasswordEncoder 인터페이스의 구현체이며 Bcrypt 해싱 함수를 사용해 비밀번호를 인코딩해주는 메서드와 사용자가 로그인할 때 제출한 비밀번호와 DB에 저장되어 있는 비밀번호의 동일 여부를 확인해주는 메서드를 제공 사람들은 여러 사이트에 동일한 아이디와 비밀번호를 사용하는데 혹여나 DB가 해킹당했을 경우 해커가 평문으로 저장된 아이디와 비밀번호를 통해 여러 사이트를 동시에 접속할 가능성이 있기 때문에 비밀번호는 항상 암호화를 한 뒤 저장해줘야한다.  이번 게시글에서는 해싱 즉, 단방향 암호화 기능을 제공하는 BcryptPasswordEncoder에 대해 공부해보겠다.

 

 

 

 

 

Spring Security에서 공식 지원하는 PasswordEncoder 구현 클래스

 

  • BcryptPasswordEncoder : Bcrypt 해시 함수를 사용하여 비밀번호 암호화
  • Argon2PasswordEncoder : Argon2 해시 함수를 사용하여 비밀번호 암호화
  • Pbkdf2PasswordEncoder : Pbkdf2 해시 함수를 사용하여 비밀번호 암호화
  • SCryptPasswordEncoder : SCrypt 해시 함수를 사용하여 비밀번호 암호화

 

 

 

 

 

BcryptPasswordEncoder

 

BCrypt는 데이터베이스에 암호화해서 넘긴다.
BCrypt는 단순히 입력을 1회 해시하는 것이 아니라, 랜덤의  
salt를 부여하여 여러번 해시를 적용하여 원래의 암호를 추측하기 어렵게 한다.

 

 

 

 

 

BcryptPasswordEncoder 메서드

 

 

String encode(CharSequence rawPassword)

  • 패스워드를 암호화해주는 메서드이며 해당 메서드는 SHA-2 이상의 알고리즘, 8바이트로 결합된 해쉬, 그리고 랜덤 하게 생성된 솔트를 지원 (SHA-1은 Hash 충돌이 발견됐기 때문에 사실상 퇴출)
  • 매개변수로 CharSequence 타입의 데이터를 넣어주면 되며 String, StringBuffer, StringBuilder 등이 이에 해당
  • 반환 타입은 String 타입
  • 똑같은 비밀번호를 입력하더라도 해당 메서드는 salt를 결합한 뒤 인코딩을 하기 때문에 매번 다른 결과가 나옴

 

boolean matches(CharSequence rawPassword, String encodePassword)

  • 입력된 평문 패스워드와 encode 메서드를 통해 인코딩된 패스워드의 동일 여부 파악에 사용
  • 첫 번째 인자로 평문 패스워드, 두 번째 패스워드로 인코딩된 패스워드
  • 반환 타입은 boolean 타입

 

boolean upgradeEncoding(String encodePassword)

  • 인코딩 된 패스워드가 안전한지 파악하는 함수
  • 매개변수로 인코딩 된 패스워드를 넣어주면
  • 반환 타입은 boolean 타입이며 안전하다면 false, 안전하지 못해서 추가적으로 인코딩해야 한다면 true 반환
  • encode() 메서드를 통해 인코딩된 암호들은 기본적으로 안전하다고 판단하여 false 반환
  • 다른 함수를 통해 인코딩된 암호의 안전 여부를 파악하는 데 사용하면 좋을 것 같음

 

pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

 

package mj_crossShot.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class AppConfig {

	/**
	 * 여기서 명시적으로 BcryptPasswordEncoder를 등록하지 않고 PasswordEncoder를 등록한 이유는 디폴트
	 * PasswordEncoder가 Bcrypt + salt를 사용하기 때문입니다.
	 */
	
	@Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
}
package mj_crossShot.service;

import java.util.Map;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import mj_crossShot.Mapper.MemberMapper;
import mj_crossShot.controller.MemberController;
import mj_crossShot.vo.Member;

@Service
public class MemberService implements MemberServiceIF {

	@Autowired
	private SqlSessionFactory sqlSessionFactory;

	@Autowired
	private MemberMapper memberMapper;

	@Autowired
	private PasswordEncoder passwordEncoder;

	/* 회원가입 */

	public void memberJoin(Member member) {

		String enPw = passwordEncoder.encode(member.getPwd());
		member.setPwd(enPw);

		try (SqlSession session = sqlSessionFactory.openSession()) {
			// 매퍼 인터페이스의 구현 클래스를 얻는 과정
			MemberMapper memberMapper = session.getMapper(MemberMapper.class);

			memberMapper.memberJoin(member);

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/* 아이디 중복 검사 */
	@Override
	public int idCheck(Map<String, Object> memId) {

		// 매퍼 인터페이스의 구현 클래스를 얻는 과정

		int cnt = memberMapper.idCheck(memId);

		return cnt;

	}
//
//	/* 로그인 */
//	@Override
//	public Member memberLogin(Member member) throws Exception {
//
//		return memberMapper.memberLogin(member);
//	}
}

 

 

 

출처 : https://jaimemin.tistory.com/2082

댓글