JAVA

[JAVA/SpringBoot] 패스워드 암호화 구현 (2-8)

wonderson 2022. 5. 29. 11:21
반응형

[여기에 적은 거는 강의 내용을 다 적은게 아니라서 강의자료 보면서 이 게시글 참고하자.]

[스프링 심화 강의 2주차 8강 패스워드 암호화 구현]

 

- springCore 프로젝트에서 실습

 

 

패스워드 암호화 적용

  1. 암호화 알고리즘을 "빈(Bean)" 으로 등록
  • 저희는 스프링 시큐리티에서 '권고'하고 있는 'BCrypt 해시함수'를 사용해 패스워드를 암호화하여 DB 에 저장하겠습니다.
@Bean
public BCryptPasswordEncoder encodePassword() {
    return new BCryptPasswordEncoder();
}

[코드스니펫] security > WebSecurityConfig - 전체 코드

- WebSecurityConfig에 @Configuration이 있다. 이 어노테이션은 서버가 처음 시작할 때 읽어서 미리 서버 세팅하는거라서 이곳에 위에 코드를 넣었다.

더보기
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity // 스프링 Security 지원을 가능하게 함
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

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

    @Override
    public void configure(WebSecurity web) {
        // h2-console 사용에 대한 허용 (CSRF, FrameOptions 무시)
        web
                .ignoring()
                .antMatchers("/h2-console/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 회원 관리 처리 API (POST /user/**) 에 대해 CSRF 무시
        http.csrf()
                .ignoringAntMatchers("/user/**");

        http.authorizeRequests()
                // image 폴더를 login 없이 허용
                .antMatchers("/images/**").permitAll()
                // css 폴더를 login 없이 허용
                .antMatchers("/css/**").permitAll()
                // 회원 관리 처리 API 전부를 login 없이 허용
                .antMatchers("/user/**").permitAll()
                // 그 외 어떤 요청이든 '인증'
                .anyRequest().authenticated()
                .and()
                // 로그인 기능
                .formLogin()
                .loginPage("/user/login")
                .defaultSuccessUrl("/")
                .failureUrl("/user/login?error")
                .permitAll()
                .and()
                // 로그아웃 기능
                .logout()
                .permitAll();
    }
}

 

[암호화 알고리즘 사용 용도]

(1) 회원 가입 시 패스워드를 암호화하여 저장

  • 직접 구현해 줘야 함

(2) 로그인 인증 시 사용

  • 스프링 시큐리티 자동으로 가져다 사용
  • 로그인 처리 시
    • 사용자가 입력한 패스워드 평문을 암호화
    • 암호화된 DB 의 패스워드와 비교

회원 가입 시 패스워드 암호화 구현

[코드스니펫] service > UserService

더보기
import com.sparta.springcore.dto.SignupRequestDto;
import com.sparta.springcore.model.User;
import com.sparta.springcore.model.UserRoleEnum;
import com.sparta.springcore.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
public class UserService {
    private final PasswordEncoder passwordEncoder;
    private final UserRepository userRepository;
    private static final String ADMIN_TOKEN = "AAABnv/xRVklrnYxKZ0aHgTBcXukeZygoC";

    @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());
        String email = requestDto.getEmail();

        // 사용자 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, email, role);
        userRepository.save(user);
    }
}

 

 

동작 검증

  • 회원 가입 후 DB 에 패스워드가 암호화되어 저장되는지 확인

반응형