본문 바로가기

TIL

37_Step : spring security로 로그인 기능 만들기(3)

 로그인 기능 만들기(2)에 살 붙이기

 

36_Step에서 spring security가 만들어준 로그인 페이지가 아닌 내가 설계한 페이지를 띄우려면 어떻게 해야 하는지에 대해 알아봤다. 로그인 페이지가 있으면 로그인을 할 수 있는 회원가입 기능을 만들어야 한다. 처음에는 security가 만들어준 ID와 password를 가지고 로그인을 했었는데 이제는 우리가 사용할 ID와 password로 회원가입 후 로그인과 회원 DB를 만들어 관리해주면 로그인 기능은 얼추 만들었다고 볼 수 있다.

 

회원가입 기능 만들기

 

일단 DB설계를 먼저 해야한다. 회원가입시 어떤 정보들을 받을 거며 그 정보들을 어떻게 관리할 것인지에 대한 설계를 하는 것이 첫 번째로 할 일이다.  간단하게 이름, 비밀번호, 관리자 정도만 입력받는 테이블을 생성했다.

 

@Setter
@Getter
@NoArgsConstructor
@Entity
public class User {

    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    private Long id;

    @Column(nullable = false, unique = true)
    private String username;
    
    @Column(nullable = false)
    private String password;
    
    @Column(nullable = false)
    @Enumerated(value = EnumType.STRING)
    private UserRoleEnum role;
    
    public User(String username, String password, UserRoleEnum role) {
        this.username = username;
        this.password = password;
        this.role = role;
    }
}

 

그리고 관리자에 대한 설정을 하는 클래스를 만들어준다.

 

public enum UserRoleEnum {
    USER,
    ADMIN
}

 

관리자 설정은 가입 시 관리자인지 일반 유저인지 구분할 수 있는 방법중 하나인데 관리자라는 것을 증명할 수 있는 관리자 가입 토큰을 만들어서 사용하는 것이 좋다.

 

 

그런 다음에는 회원가입 정보를 전달해주는 Dto를 만들고, controller, service, repository를 만들어준 후에 만들 것들이 잘 연결되어 구동되는지 테스트를 해본다. h2콘솔을 이용해 회원정보가 잘 들어가 있는지 확인한다.

 

@Override
public void configure(WebSecurity web) {
    
    web
        .ignoring()
        .antMatchers("/h2-console/**");
}
	http.csrf()
		.ignoringAntMatchers("/user/**");

 

 

위의 내용은 쉽게 말해 h2-console 사용에 대한 오류를 허용하여 쓸 수 있게 하는 코드로  WebSecurityConfig에 입력해준다. 또한 여기에 아래 내용을 입력해줘서 우리가 설정해놨던 회원 관리 처리 API (POST /user/**) 에 대해 CSRF 무시를 할 수 있도록 해준다.

 

 

이렇게 해주면 h2콘솔을 통해 정보를 볼 수 있는데 이게 또 문제가 된다. 보통 가입시 ID는 공개되지만 password는 본인만 알게 하기 마련이다. 그런데 위의 방법대로 하면 관리자가 유저의 ID뿐만 아니라 password까지 다 볼 수 있게 된다. 관리자조차도 모르게 확실한 보안을 위해서는 security의 도움을 받으면 된다.

 

 

@Bean
public BCryptPasswordEncoder encodePassword() {
	return new BCryptPasswordEncoder();
}

 

 

위의 내용을 WebSecurityConfig에 입력해주면 security가 BCrypt 해시함수를 토대로 하여 암호화한 뒤 DB에 저장한다.

이렇게 되면 회원가입시에는 password를 암호화하여 DB에 저장을 하고, 로그인을 시도했을 때는 입력한 password를 암호화하여 기존의 DB에 있는 암호화된 password와 비교하여 확인하는 절차를 진행하게 된다.

 

 

 

WebSecurityConfig에 설정을 해줬다면 Service에도 수정해야 할 부분이 있다.

 

 

@Service
public class UserService {

    private final PasswordEncoder passwordEncoder;
    private final UserRepository userRepository;
    private static final String ADMIN_TOKEN = "djlJODUiWMjh/sUWojmSKnDf";

    @Autowired
    public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }

    public void registerUser(SignupRequestDto requestDto) {

        // 회원 ID 중복 확인
        String username = requestDto.getUsername();
        Optional<User> found = userRepository.findByUsername(username);
        if (found.isPresent()) {
        throw new IllegalArgumentException("중복된 사용자 ID 가 존재합니다.");
        }

        // 패스워드 암호화
        String password = passwordEncoder.encode(requestDto.getPassword());

        // 사용자 ROLE 확인
        UserRoleEnum role = UserRoleEnum.USER;
        if (requestDto.isAdmin()) {
            if (!requestDto.getAdminToken().equals(ADMIN_TOKEN)) {
            throw new IllegalArgumentException("관리자 암호가 틀려 등록이 불가능합니다.");
            }
        	role = UserRoleEnum.ADMIN;
    	}
        
        User user = new User(username, password, role);
        userRepository.save(user);
    }
}

 

 

 

이처럼 Service 부분에서도 passwordEncoder를 활용하면 password를 입력하고 로그인을 시도했을 시에 암호화하여 DB에 들어가게 된다. 그 암호화된 password가 DB의 회원가입시 암호화 되어 있는 정보와 일치하면 로그인에 성공하게 되는 것이다. 

 

 

 

 

 

 

최종적으로 h2콘솔을 보면 ID와 관리자 상태, 암호화된 비밀번호가 잘 들어가 있음을 볼 수 있다.

 

 

 

security는 정말 편리하게 보안 기능을 설정해주고 관리해 주지만 기능이 많은 만큼 복잡하고, 어려울 수도 있다. 그래도 어느정도 익혀놓으면 직접 손으로 다 만드는 것보다는 훨씬 쓰기 좋으니 다는 못하더라도 본인이 필요한 정도는 공부해보는 것을 추천한다.