종우의 삶 (전체 공개)

Spring Security - 1 본문

개발/Spring

Spring Security - 1

jonggae 2024. 1. 14. 18:39

대상 Repository : https://github.com/Jonggae/security

Security와 관련된 내용들을 연습한다.

 


issue 1 :  회원 가입 기능

 

현재 Security 기능 중 유저 회원 가입을 개발하고있다.

 

최대한 단순하게 로직을 구상했고 

 

가입하려는 회원은

 

username ; 로그인에 필요한 ID 처럼 쓰일 예정

password ; 비밀번호

email ; 메일주소 

 

이상 3가지의 필드를 입력하여야한다.

 

이 중 password는 db에 저장이 되기 전에 암호화되며 보안성을 높이게 된다.

 

메인 로직 코드

코드를 전부 올리기에는 번거로우므로 깃허브를 참조한다. 

이슈가 생긴 코드는 언급하여 함께 설명한다.

 

우선 UserService 에서 간단한 정보 3가지를 받아 회원가입을 진행하는 메서드를 생성한다.

 

package com.example.securitydemo.user.service;

import com.example.securitydemo.user.dto.RegisterRequestDto;
import com.example.securitydemo.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class UserService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    public void register(RegisterRequestDto requestDto) {
        checkUserinfo(requestDto.getUsername(), requestDto.getEmail());
        userRepository.save(requestDto.toEntity(passwordEncoder));
    }

    public void checkUserinfo(String username, String email) {
        checkUsername(username);
        checkEmail(email);
    }

    public void checkUsername(String username) {
        if (userRepository.findByUsername(username).isPresent()) {
            throw new IllegalArgumentException("이미 사용중인 아이디입니다");
        }
    }

    public void checkEmail(String email) {
        if (userRepository.findByEmail(email).isPresent()) {
            throw new IllegalArgumentException("이미 사용중인 이메일입니다");
        }
    }

}

 

checkUserinfo를 통해 이미 사용중인 아이디, 이메일인지 검사하고 예외에 걸리지 않으면

Repository.save로 저장을 하는 방식이다. 

 

이전에 겪었던 메서드 분리들을 비슷하게 해보았는데 짧은코드라 그런지 티는 별로 나지 않지만 

무언가 더 알아보기 쉬워지긴 하였다.

 

사실 문제는 Dto에서 나타났다. 메인 로직에서 오류는 나타나지 않았지만

PasswordEncoder를 사용하는데 테스트코드에서 많은 오류가 발생하고 있다.

 

회원가입에 필요한 정보를 담아오는 RegisterRequestDto를 보자

 

RegisterRequestDto.java

package com.example.securitydemo.user.dto;

import com.example.securitydemo.user.domain.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class RegisterRequestDto {

    private String username;
    private String password;
    private String email;


//   public void setPassword(String password) {
//       this.password = password;
//   }

    public User toEntity(PasswordEncoder passwordEncoder) {
        return User.builder()
                .username(username)
                .password(encodePassword(passwordEncoder))
                .email(email)
                .build();
    }

    private String encodePassword(PasswordEncoder passwordEncoder) {
        return passwordEncoder.encode(password);
    }

}

 

주석된 코드를 남겨놓은 것은 여러 방법을 돌아왔기 때문인데,

 

우선 password는 암호화를 하여 저장을 하기 때문에 

repository query를 보내기 전에 암호화하여야한다.

 

PasswordEncoder를  @Bean으로 주입받아 사용한다. (SecurityConfig 클래스에 포함)

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

 

builder()를 이용하여 객체를 생성할 때, 비밀번호를 암호화하게 만들었다.

 

Service 레이어에서 암호화를 할지, 이 Dto 레이어에서 암호화를 할지 여러 시도가 있었지만

큰 문제는 아닌것 같은.. 암호화만 잘 되면 된다고 생각하여 그냥 보기 좋은 것으로 선택했다. (service 코드가 짧아짐)

 

개발 패턴에 어울리지 않거나, 문제가 발생할 가능성이 있다면 다른 방법으로 사용하는 것이 좋을 것이다.

 

어찌되었든 기능자체는 단순하게 개발하였으므로 Controller까지 완성한 후 api테스트를 진행했다.

 

IDE 내에서 바로 api요청을 날려본다. 

 

 

이렇게 성공하고.. h2 DB에도 들어가는 것을 확인하였다.

어렵지 않은 기능이었으므로 문제가 없을 줄 알았다..

 

 

'개발 > Spring' 카테고리의 다른 글

Spring security - 4  (0) 2024.01.17
Spring security - 3 // Security Config  (0) 2024.01.15
Spring security - 2  (0) 2024.01.14
Code refactoring - 2  (1) 2024.01.10
Code refactoring - 1  (1) 2023.12.31
Comments