Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- 자료구조와 함께 배우는 알고리즘 입문
- 자바편
- network configuration
- 코드로배우는스프링부트웹프로젝트
- 자료구조와함께배우는알고리즘입문
- /etc/network/interfaces
- GIT
- 친절한SQL튜닝
- Kernighan의 C언어 프로그래밍
- 구멍가게코딩단
- 서버설정
- 페이징
- 스프링 시큐리티
- 데비안
- iterator
- 코드로배우는스프링웹프로젝트
- baeldung
- 리눅스
- 네트워크 설정
- resttemplate
- 선형대수
- 스프링부트핵심가이드
- 이터레이터
- 처음 만나는 AI 수학 with Python
- 목록처리
- ㅒ
- 티스토리 쿠키 삭제
- 처음 만나는 AI수학 with Python
- 알파회계
- d
Archives
- Today
- Total
bright jazz music
blog41 : 회원가입과 비밀번호 암호화-4 본문
- 테스트 케이스 개선
로컬에서 테스트 할 때는 굳이 암호화하여 테스트 할 필요 없으므로 평문을 사용하는 PasswordEncoder를 하나 더 생성하여 테스트 해볼 수 있다. 따라서 로컬에서 테스트 할 때는 평문을 사용하는 encoder를 주입하고, 운영에서는 암호화를 사용하는 encoder를 사용하는 것이다. 그렇게 하면 asserEquals()를 사용하여 테스트 할 수 있다.
1.PasswordEncoder 인터페이스 생성
//PasswordEncoder.java
package com.endofma.blog.crypto;
public interface PasswordEncoder {
String encrypt(String rawPassword);
boolean matches(String rawPassword, String encryptedPassword);
}
- 기존의 PasswordEncoder클래스의 이름을 ScryptPasswordEncoder로 변경하고 이 인터페이스를 구현하도록 만든다.
- PlainPasswordEncoder를 생성하여 이 인터페이스를 구현하도록 만든다.
- 스프링 자체에서 제공하는 PasswordEncoder가 존재하므로 잘못 구현하지 않도록 주의
1. PasswordEncoder를 ScryptPasswordEncoder로 이름 변경하고 PasswordEncoder 인터페이스 구현 (운영 시 사용할 클래스)
//PasswordEncoder.java
package com.endofma.blog.crypto;
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
import org.springframework.stereotype.Component;
@Component //이걸 붙여주면 인스턴스를 매번 생성할 필요 없이 주입해서 사용할 수 있다.
public class ScryptPasswordEncoder implements PasswordEncoder{
private static final SCryptPasswordEncoder encoder
= new SCryptPasswordEncoder(16, 8, 1, 32, 64);
@Override
public String encrypt(String rawPassword) {
return encoder.encode(rawPassword);
}
@Override
public boolean matches(String rawPassword, String encryptedPassword) {
return encoder.matches(rawPassword, encryptedPassword);
}
}
2. PlainPasswordEncoder 생성( 로컬 테스트용)
//PlainPasswordEncoder.java
package com.endofma.blog.crypto;
import org.springframework.stereotype.Component;
@Component
public class PlainPasswordEncoder implements PasswordEncoder{
@Override
public String encrypt(String rawPassword) {
return rawPassword;
}
@Override
public boolean matches(String rawPassword, String encryptedPassword) {
return rawPassword.equals(encryptedPassword);
}
}
4. 테스트 시 PlainPasswordEncoder 로 주입하도록 설정하기
4.1 AuthServiceTest.java에 @ActiveProfiles() 설정
//AuthServiceTest.java
package com.endofma.blog.service;
import com.endofma.blog.crypto.PasswordEncoder;
import com.endofma.blog.crypto.PlainPasswordEncoder;
import com.endofma.blog.domain.User;
import com.endofma.blog.exception.AlreadyExistsEmailException;
import com.endofma.blog.exception.InvalidSigninInformation;
import com.endofma.blog.repository.UserRepository;
import com.endofma.blog.request.Login;
import com.endofma.blog.request.Signup;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.function.Executable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import static org.junit.jupiter.api.Assertions.*;
@ActiveProfiles("test") //실행 시 test라는 profile로 실행할 것
@SpringBootTest
class AuthServiceTest {
@Autowired
private UserRepository userRepository;
@Autowired
private AuthService authService;
@AfterEach
void clean() { userRepository.deleteAll();}
//AuthServiceTest.java
@Test
@DisplayName("회원가입")
void test1(){
//given
Signup signup = Signup.builder()
.email("catnails@gmail.com")
.password("1234")
.name("catnails")
.build();
//when
authService.signup(signup);
//then
Assertions.assertEquals(1, userRepository.count());
User user = userRepository.findAll().iterator().next();
Assertions.assertEquals("catnails@gmail.com", user.getEmail());
Assertions.assertNotNull(user.getPassword());
// Assertions.assertNotEquals("1234", user.getPassword());
Assertions.assertEquals("1234", user.getPassword());
Assertions.assertEquals("catnails", user.getName());
}
//AuthServiceTest.java
@Test
@DisplayName("회원가입 시 중복된 이메일")
void test2(){
//given
User user = User.builder()
.name("catnails")
.email("catnails@gmail.com")
.password("1234")
.build();
userRepository.save(user);
Signup signup = Signup.builder()
.email("catnails@gmail.com")
.password("1234")
.name("catnails")
.build();
//expected
Assertions.assertThrows(AlreadyExistsEmailException.class, () -> authService.signup(signup));
}
//AuthServiceTest.java
@Test
@DisplayName("로그인 성공")
void test3(){
//given
// PasswordEncoder encoder = new PasswordEncoder(); 평문으로 테스트 하기로 했으므로 주석처리
PlainPasswordEncoder encoder = new PlainPasswordEncoder();
String encryptedPassword = encoder.encrypt("1234");
User user = User.builder()
.email("catnails@gmail.com")
.password(encryptedPassword)
.name("catnails")
.build();
userRepository.save(user);
// authService.signup(signup);
Login login = Login.builder()
.email("catnails@gmail.com")
.password("1234")
.build();
//when
Long userId = authService.signin(login);
//then
Assertions.assertNotNull(userId);
}
//AuthServiceTest.java
@Test
@DisplayName("로그인 시 비밀번호 틀림")
void test4(){
//given
// PasswordEncoder encoder = new PasswordEncoder(); 평문으로 테스트 하기로 했으므로 주석처리
PlainPasswordEncoder encoder = new PlainPasswordEncoder();
String encryptedPassword = encoder.encrypt("1234");
User user = User.builder()
.email("catnails@gmail.com")
.password(encryptedPassword)
.name("catnails")
.build();
userRepository.save(user);
Login login = Login.builder()
.email("catnails@gmail.com")
.password("5678") //비밀번호 틀림
.build();
//expected
Assertions.assertThrows(InvalidSigninInformation.class,
() -> authService.signin(login));
}
}
@ActiveProfiles("test")를 사용하여 test라는 profile을 사용할 것을 명시하였다.
4.2 PlainPasswordEncoder에 @Profile() 어노테이션 설정
//PlainPasswordEncoder.java
package com.endofma.blog.crypto;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
@Profile("test") //prifile이 "test"일 경우에만 bean으로 생성
@Component
public class PlainPasswordEncoder implements PasswordEncoder{
@Override
public String encrypt(String rawPassword) {
return rawPassword;
}
@Override
public boolean matches(String rawPassword, String encryptedPassword) {
return rawPassword.equals(encryptedPassword);
}
}
@Profile("test")를 명시하여 PlainPasswordEncoder가 test임을 명시하였다.
4.3 ScryptPasswordEncoder에 @Profile() 어노테이션 설정
반드시 @Profile("test")가 아님을 명시해 줄 것. default를 사용
//PasswordEncoder.java
package com.endofma.blog.crypto;
import org.springframework.context.annotation.Profile;
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
import org.springframework.stereotype.Component;
@Profile("default") //반드시 설정해 줘야한다. 설정이 test라도 여기에 test가 아님을 명시하지 않으면 bean으로생 성된다.
@Component //이걸 붙여주면 인스턴스를 매번 생성할 필요 없이 주입해서 사용할 수 있다.
public class ScryptPasswordEncoder implements PasswordEncoder{
private static final SCryptPasswordEncoder encoder
= new SCryptPasswordEncoder(16, 8, 1, 32, 64);
@Override
public String encrypt(String rawPassword) {
return encoder.encode(rawPassword);
}
@Override
public boolean matches(String rawPassword, String encryptedPassword) {
return encoder.matches(rawPassword, encryptedPassword);
}
}
5. 테스트
'Projects > blog' 카테고리의 다른 글
blog40 : 회원가입과 비밀번호 암호화-3 (0) | 2023.02.26 |
---|---|
blog39 : 회원가입과 비밀번호 암호화-2 (0) | 2023.02.26 |
blog38 : 회원가입과 비밀번호 암호화-1 (0) | 2023.02.26 |
blog37 : JWT를 이용한 인증 - 암호화 키 분리 및 개선 (0) | 2023.02.23 |
blog36 : JWT를 이용한 인증 - application.yml 커스텀 설정값 만들기 (0) | 2023.02.22 |
Comments