From 568ca21c209b54c01ced534b7a8475f1f1f35697 Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Fri, 12 Apr 2024 21:49:07 +0900 Subject: [PATCH 1/3] =?UTF-8?q?chore:=20bcrypt=20=ED=95=B4=EC=8B=9C=20?= =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index ac3a27e..171f5c5 100644 --- a/build.gradle +++ b/build.gradle @@ -42,6 +42,9 @@ dependencies { runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.3' runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.3' + //crypto + implementation 'org.mindrot:jbcrypt:0.4' + compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' runtimeOnly 'com.mysql:mysql-connector-j' From f299ca641277004076a6adcd4c09112c0b08cb3d Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Fri, 12 Apr 2024 22:16:14 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20BCrypt=20=ED=8C=A8=EC=8A=A4?= =?UTF-8?q?=EC=9B=8C=EB=93=9C=20=EC=9D=B8=EC=BD=94=EB=8D=94=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/crypto/BCryptPasswordEncoder.java | 22 ++++ .../crypto/BCryptPasswordEncoderTest.java | 104 ++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 src/main/java/com/seong/shoutlink/global/auth/crypto/BCryptPasswordEncoder.java create mode 100644 src/test/java/com/seong/shoutlink/global/auth/crypto/BCryptPasswordEncoderTest.java diff --git a/src/main/java/com/seong/shoutlink/global/auth/crypto/BCryptPasswordEncoder.java b/src/main/java/com/seong/shoutlink/global/auth/crypto/BCryptPasswordEncoder.java new file mode 100644 index 0000000..83a2070 --- /dev/null +++ b/src/main/java/com/seong/shoutlink/global/auth/crypto/BCryptPasswordEncoder.java @@ -0,0 +1,22 @@ +package com.seong.shoutlink.global.auth.crypto; + +import com.seong.shoutlink.domain.auth.PasswordEncoder; +import org.mindrot.jbcrypt.BCrypt; + +public class BCryptPasswordEncoder implements PasswordEncoder { + + @Override + public String encode(String rawPassword) { + return BCrypt.hashpw(rawPassword, BCrypt.gensalt()); + } + + @Override + public boolean isMatches(String rawPassword, String encodedPassword) { + return BCrypt.checkpw(rawPassword, encodedPassword); + } + + @Override + public boolean isNotMatches(String rawPassword, String encodedPassword) { + return !isMatches(rawPassword, encodedPassword); + } +} diff --git a/src/test/java/com/seong/shoutlink/global/auth/crypto/BCryptPasswordEncoderTest.java b/src/test/java/com/seong/shoutlink/global/auth/crypto/BCryptPasswordEncoderTest.java new file mode 100644 index 0000000..1d2dfd6 --- /dev/null +++ b/src/test/java/com/seong/shoutlink/global/auth/crypto/BCryptPasswordEncoderTest.java @@ -0,0 +1,104 @@ +package com.seong.shoutlink.global.auth.crypto; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +class BCryptPasswordEncoderTest { + + BCryptPasswordEncoder bCryptPasswordEncoder; + + @BeforeEach + void setUp() { + bCryptPasswordEncoder = new BCryptPasswordEncoder(); + } + + @Nested + @DisplayName("encode 호출 시") + class EncodeTest { + + @Test + @DisplayName("성공: 일방향 해싱됨") + void encode() { + //given + String password = "asdf1234!"; + + //when + String encoded = bCryptPasswordEncoder.encode(password); + + //then + assertThat(encoded).isNotEqualTo(password); + } + } + + @Nested + @DisplayName("matches 호출 시") + class MatchesTest { + + @Test + @DisplayName("성공: 플레인 텍스트와 해시값이 동일하면 true") + void matches_ThenTrue() { + //given + String password = "asdf1234!"; + String encoded = bCryptPasswordEncoder.encode(password); + + //when + boolean result = bCryptPasswordEncoder.isMatches(password, encoded); + + //then + assertThat(result).isTrue(); + } + + @Test + @DisplayName("성공: 플레인 텍스트와 해시값이 동일하지 않으면 false") + void noneMatches_ThenFalse() { + //given + String password = "asdf1234!"; + String encoded = bCryptPasswordEncoder.encode(password); + String noneMatches = password + "a"; + + //when + boolean result = bCryptPasswordEncoder.isMatches(noneMatches, encoded); + + //then + assertThat(result).isFalse(); + } + } + + @Nested + @DisplayName("noneMatches 호출 시") + class NoneMatchesTest { + + @Test + @DisplayName("성공: 플레인 텍스트와 해시값이 동일하지 않으면 true") + void noneMatches_ThenTrue() { + //given + String password = "asdf1234!"; + String encoded = bCryptPasswordEncoder.encode(password); + String noneMatch = password + "a"; + + //when + boolean result = bCryptPasswordEncoder.isNotMatches(noneMatch, encoded); + + //then + assertThat(result).isTrue(); + } + + @Test + @DisplayName("성공: 플레인 텍스트와 해시값이 동일하면 false") + void matches_ThenFalse() { + //given + String matches = "asdf1234!"; + String encoded = bCryptPasswordEncoder.encode(matches); + + //when + boolean result = bCryptPasswordEncoder.isNotMatches(matches, encoded); + + //then + assertThat(result).isFalse(); + } + } +} From 0723510976874196d8563c26f8b56a9fa40716e7 Mon Sep 17 00:00:00 2001 From: hseong3243 Date: Fri, 12 Apr 2024 22:17:40 +0900 Subject: [PATCH 3/3] =?UTF-8?q?chore:=20BCrypt=20=ED=8C=A8=EC=8A=A4?= =?UTF-8?q?=EC=9B=8C=EB=93=9C=20=EC=9D=B8=EC=BD=94=EB=8D=94=20Bean=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/SimplePasswordEncoder.java | 19 ------------------- .../shoutlink/global/config/AuthConfig.java | 4 ++-- 2 files changed, 2 insertions(+), 21 deletions(-) delete mode 100644 src/main/java/com/seong/shoutlink/domain/auth/SimplePasswordEncoder.java diff --git a/src/main/java/com/seong/shoutlink/domain/auth/SimplePasswordEncoder.java b/src/main/java/com/seong/shoutlink/domain/auth/SimplePasswordEncoder.java deleted file mode 100644 index 8ed1255..0000000 --- a/src/main/java/com/seong/shoutlink/domain/auth/SimplePasswordEncoder.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.seong.shoutlink.domain.auth; - -public class SimplePasswordEncoder implements PasswordEncoder { - - @Override - public String encode(String rawPassword) { - return new StringBuilder(rawPassword).reverse().toString(); - } - - @Override - public boolean isMatches(String rawPassword, String encodedPassword) { - return encode(rawPassword).equals(encodedPassword); - } - - @Override - public boolean isNotMatches(String rawPassword, String encodedPassword) { - return !isMatches(rawPassword, encodedPassword); - } -} diff --git a/src/main/java/com/seong/shoutlink/global/config/AuthConfig.java b/src/main/java/com/seong/shoutlink/global/config/AuthConfig.java index 58a4974..fe6b9ef 100644 --- a/src/main/java/com/seong/shoutlink/global/config/AuthConfig.java +++ b/src/main/java/com/seong/shoutlink/global/config/AuthConfig.java @@ -2,9 +2,9 @@ import com.seong.shoutlink.domain.auth.JwtProvider; import com.seong.shoutlink.domain.auth.PasswordEncoder; -import com.seong.shoutlink.domain.auth.SimplePasswordEncoder; import com.seong.shoutlink.global.auth.authentication.AuthenticationContext; import com.seong.shoutlink.global.auth.authentication.JwtAuthenticationProvider; +import com.seong.shoutlink.global.auth.crypto.BCryptPasswordEncoder; import com.seong.shoutlink.global.auth.jwt.JJwtProvider; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -25,7 +25,7 @@ public JwtProvider jwtProvider( @Bean public PasswordEncoder passwordEncoder() { - return new SimplePasswordEncoder(); + return new BCryptPasswordEncoder(); } @Bean