diff --git a/build.gradle b/build.gradle index ea890b2..73d5cfc 100644 --- a/build.gradle +++ b/build.gradle @@ -16,9 +16,9 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.springframework.boot:spring-boot-starter-jdbc:2.7.3' implementation 'org.projectlombok:lombok:1.18.24' annotationProcessor 'org.projectlombok:lombok' @@ -32,6 +32,8 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.boot:spring-boot-starter-jdbc:2.7.3' + testImplementation 'org.springframework.security:spring-security-test' } tasks.named('test') { diff --git a/src/main/java/com/io/realworld/config/WebConfig.java b/src/main/java/com/io/realworld/config/WebConfig.java new file mode 100644 index 0000000..8bfdadb --- /dev/null +++ b/src/main/java/com/io/realworld/config/WebConfig.java @@ -0,0 +1,34 @@ +package com.io.realworld.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import org.springframework.http.HttpStatus; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.HttpStatusEntryPoint; + + +@Configuration +@EnableWebSecurity +public class WebConfig { + + + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http.csrf() + .disable() + .authorizeRequests() + .antMatchers("/users/**","/h2-console/**").permitAll() + .anyRequest().authenticated() + .and().headers().frameOptions().sameOrigin() + .and() + .formLogin() + .disable() + .exceptionHandling() + .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)); + return http.build(); + } +} diff --git a/src/main/java/com/io/realworld/service/UserServiceImpl.java b/src/main/java/com/io/realworld/service/UserServiceImpl.java index aade78e..07a3368 100644 --- a/src/main/java/com/io/realworld/service/UserServiceImpl.java +++ b/src/main/java/com/io/realworld/service/UserServiceImpl.java @@ -6,22 +6,34 @@ import com.io.realworld.Exception.Error; import com.io.realworld.repository.User; import com.io.realworld.repository.UserRepository; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service +@Transactional(readOnly = true) public class UserServiceImpl implements UserService { @Autowired private UserRepository userRepository; + + + @Transactional public User signup(UserSignupRequest userSignupRequest) { if (userRepository.findByEmail(userSignupRequest.getEmail()) != null) { throw new CustomException(Error.DUPLICATE_USER); } else { + String hashPw = madeHash(userSignupRequest.getPassword()); return userRepository.save(User.of(userSignupRequest.getUsername(), userSignupRequest.getEmail(), - userSignupRequest.getPassword())); + hashPw)); } } + private String madeHash(String password){ + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.encode(password); + } + } diff --git a/src/test/java/com/io/realworld/api/users/UserControllerTest.java b/src/test/java/com/io/realworld/api/users/UserControllerTest.java index 0c7baa2..84c6120 100644 --- a/src/test/java/com/io/realworld/api/users/UserControllerTest.java +++ b/src/test/java/com/io/realworld/api/users/UserControllerTest.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.io.realworld.DTO.UserSignupRequest; import com.io.realworld.repository.User; import com.io.realworld.service.UserServiceImpl; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mockito; @@ -11,12 +12,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import static org.mockito.ArgumentMatchers.any; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -38,6 +41,8 @@ class UserControllerTest { @Test + @WithMockUser + @DisplayName("회원가입 컨트롤러 테스트") void signup() throws Exception { //given UserSignupRequest signupRequestTest = getUserSignupRequest(); @@ -50,6 +55,7 @@ class UserControllerTest { post("/users") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(signupRequestTest)) + .with(csrf()) ); diff --git a/src/test/java/com/io/realworld/service/UserServiceImplTest.java b/src/test/java/com/io/realworld/service/UserServiceImplTest.java index e2b7d20..171946d 100644 --- a/src/test/java/com/io/realworld/service/UserServiceImplTest.java +++ b/src/test/java/com/io/realworld/service/UserServiceImplTest.java @@ -1,12 +1,29 @@ package com.io.realworld.service; +import com.io.realworld.repository.UserRepository; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import static org.junit.jupiter.api.Assertions.*; +@ExtendWith(MockitoExtension.class) class UserServiceImplTest { + @InjectMocks + UserServiceImpl userService; + + @Mock + UserRepository userRepository; + @Test + @DisplayName("회원가입_서비스_테스트") void signup() { + return; } } \ No newline at end of file