지금까지는 평문으로 저장해 1초만에 해킹당할 것 같은 비밀번호였다면, 이번에는 비밀번호 암호화를 통해 저장해봤다.
가장 먼저 dependencies에 아래 의존성을 추가해야한다.
implementation 'at.favre.lib:bcrypt:0.10.2'
그리고 config 패키지 안에 PasswordEncoder
클래스를 추가한다. BCrypt 라이브러리를 활용하여 비밀번호를 안전하게 처리할 수 있는 클래스다. 평문 비밀번호를 암호화할 때는 encode()
를 사용해 복잡한 값으로 만들어준다. 로그인할 때나 정보를 수정할 때 그렇게 저장된 비밀번호를 matches()
를 이용해 유저가 입력한 비밀번호와 비교한다.
import at.favre.lib.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Component;
@Component
public class PasswordEncoder {
public String encode(String rawPassword) {
return BCrypt.withDefaults().hashToString(BCrypt.MIN_COST, rawPassword.toCharArray());
}
public boolean matches(String rawPassword, String encodedPassword) {
BCrypt.Result result = BCrypt.verifyer().verify(rawPassword.toCharArray(), encodedPassword);
return result.verified;
}
}
회원가입할 때를 제외하고는 전부 matches()
로 비교하면 돼서 비교적 간단하게 끝났다.
// 비밀번호 암호화
String encodedPassword = passwordEncoder.encode(dto.getPassword());
Member member = new Member(dto.getUsername(), dto.getEmail(), encodedPassword);
Member savedMember = memberRepository.save(member);
// 비밀번호 일치 여부 판단
boolean isMatch = passwordEncoder.matches(dto.getPassword(), member.getPassword());
if (!isMatch) {
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "비밀번호가 일치하지 않습니다.");
}
@PostMapping("/login")
public ResponseEntity<Void> login(
@RequestBody LoginRequestDto dto,
HttpServletRequest request
) {
MemberResponseDto memberResponseDto = memberService.authenticate(dto);
HttpSession session = request.getSession(true);
session.setAttribute("sessionKey", memberResponseDto.getEmail());
return ResponseEntity.ok().build();
}
@PostMapping("/logout")
public ResponseEntity<Void> logout(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
return ResponseEntity.ok().build();
}