있을 유, 참 진

[JWT] JWT 회원가입 구현하기 본문

Spring/JWT

[JWT] JWT 회원가입 구현하기

U_ma 2023. 4. 7. 15:38
회원가입 DTO
Controller 및 SecurityConfig 설정
  - Controller
  - SecurityConfig
UserService
테스트 결과

회원가입 DTO

@Getter
@NoArgsConstructor @AllArgsConstructor
public class UserDto {
  @NotNull
  @Size(min = 3, max = 50)
  private String userName;
  @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
  @NotNull
  @Size(min = 3, max = 50)
  private String password;
  @NotNull
  @Size(min = 3, max = 50)
  private String nickName;
}

@NotNull, @Size를 통해 Validation 검증은 진행한다. password에는 @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)를 통해 JSON 직렬화 보안 설정

Controller 및 SecurityConfig 설정

Controller

@RequiredArgsConstructor
@RequestMapping("/api/auth")
@RestController
public class AuthApi {
  private final UserService userService;

  @PostMapping("/sign-up")
  public ResponseEntity<User> signUp(@Valid @RequestBody UserDto userDto) {
      return ResponseEntity.status(HttpStatus.CREATED).body(this.userService.join(userDto));
  }
}

SecurityConfig

@RequiredArgsConstructor
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    // 회원가입 시 비밀번호 암호화를 위한 PasswordEncoder 빈 등록
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }    

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                //ServletRequest를 사용하는 요청에 대한 접근 제한 설정
                .authorizeRequests()
                //검증 없이 이용가능(Post 요청 가능)
                .antMatchers(HttpMethod.POST, "/api/auth/**").permitAll()
                .anyRequest().authenticated()
    }
}
  • Spring Security 설정을 위한 Configuration 파일에, “/api/auth/”로 시작하는 POST 요청에 대해서는 모두가 접근 가능
  • 들어오는 정보의 암호화를 위해서 사용할 PasswordEncoder에 대한 @Bean을 등록해 준다.

UserService

@RequiredArgsConstructor
@Service
public class UserService implements UserDetailsService {
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    @Transactional
    public User join(UserDto userDto) {
        // 1. 유저의 존재에 대한 검증
        this.userRepository.findByUsername(userDto.getUserName()).ifPresent(user ->
                new RuntimeException(user.getUserId() + "는 이미 존재하는 아이디입니다."));
        // 2. 유저의 접근 권한 설정
        Authority authority = Authority.builder()
                .name("ROLE_USER")
                .build();
        //3. 유저 정보 저장
        User user = User.builder()
                .username(userDto.getUserName())
                .password(this.passwordEncoder.encode(userDto.getPassword()))
                .nickname(userDto.getNickName())
                .activated(true)
                .authorities(Collections.singleton(authority))
                .build();

        return this.userRepository.save(user);
    }
}

테스트 결과

💡 성공적으로 201 코드를 반환하고, 저장된 결괏값을 보여준다.
class AuthApiTest extends BaseTest {
    @Test
    @DisplayName("유저 회원가입 테스트")
    void signUp_test() throws Exception {
        UserDto userDto = new UserDto(
                "Jinjinjara",
                "1q2w3e4r!",
                "Jinjinjara"
        );

        mvc.perform(
                post("/api/auth/sign-up")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(userDto))
        ).andDo(print())
                .andExpect(
                        status().isCreated()
                );
    }
}
{
    "userId":3,
    "username":"Jinjinjara",
    "password":"$2a$10$WQNEFyemzFsiOqGKICWAn.kO4cG8tNnz5RPN.eEIYfGelVyxkBruq",
    "nickname":"Jinjinjara",
    "activated":true,
    "authorities":[
        {"name":"ROLE_USER"}
    ]
}
수정 로그
23 - 04 - 07: 목차 추가
23 - 04 - 11: 제목 변경(로그인 구현하기 -> 회원가입 구현하기), 태그변경
Comments