Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: 사용자 암호는 안전한 해시 함수로 일방향 암호화한다. #79

Merged
merged 3 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -25,7 +25,7 @@ public JwtProvider jwtProvider(

@Bean
public PasswordEncoder passwordEncoder() {
return new SimplePasswordEncoder();
return new BCryptPasswordEncoder();
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
Loading