행복을 담는 블로그

[Spring Boot] 스프링 부트로 User 회원가입 / 로그인 기능 구현 + 비밀번호 암호화하기 본문

BackEnd/Spring Boot

[Spring Boot] 스프링 부트로 User 회원가입 / 로그인 기능 구현 + 비밀번호 암호화하기

hyun0zin 2024. 11. 18. 10:52

미니 프로젝트를 시작하면서,,, 다시 기록을 시작해보고자 한다.

이번 프로젝트에서는 백엔드 기능은 Spring Boot로 구현하고, 프론트는 Vue로, DB는 MySQL을 활용하여 진행하였다.

Spring Boot를 배우면서 로그인/회원가입 기능을 세션으로 구현하는 것부터 시작하였는데, 이부분에 대해서 작성해보고자 한다.

이후에는 세션으로 진행한 로그인을 JWT 토큰으로 로그인하는 기능으로 수정하였다.



프로젝트 시작에 앞서, 자동으로 Getter, Setter, 생성자를 추가해주는 Lombok이라는 의존성을 pom.xml에 추가했는데,

결과적으로 getter/setter가 생성이 안 되어서 회원가입 기능이 제대로 구현되지 않았다.

이부분에 대해서는 추가로 공부해보고 진행해야 할 것 같다.



1. 회원가입 기능 구현하기

회원가입 시, 비밀번호 암호화하여 데이터베이스 저장하기

1. pom.xml

: 암호화 시, 사용할 의존성 추가하기

  • spring boot starter security를 추가
    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

2. SecurityConfig 만들기

  • 클래스 위에 @Configuration, @EnableWebSecurity 작성
  • PasswordEncoder Bean 등록하기
  • SecurityFilterChain Bean을 만들어 cors, csrf 방지한다.
/* SecurityConfig */

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig {

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

        @Bean
        public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
            http.cors().disable()            //cors 방지
                .csrf().disable()            //csrf 방지
                .formLogin().disable()        //기본 로그인페이지 없애기
                .headers().frameOptions().disable();

            return http.build();
        }

    }



HttpSecurity 구성 알아보기

  1. CORS 방지
http.cors().disable() // CORS 방지
  • cors() : Cross-Origin Resource Sharing를 관리하는 설정. 브라우저에서 다른 도메인의 리소스에 대한 요청을 제어하는 보안 기능
  • disable() : CORS 비활성화. 브라우저에서 모든 도메인에서의 리소스 요청을 허용하지 않도록

❗주의❗ : API 서버에서 외부 도메인에서의 접근을 허용하려면 cors().disable() 대신 cors().configurationSource() 등을 사용해 특정 도메인에서의 접근을 허용하는 게 좋다.


  1. CSRF 방지
.csrf().disable() // CSRF 방지
  • csrf() : Cross-Site Request Forgery(CSRF) 공격 방지를 위한 설정

  • Cross-Site Request Forgery (CSRF) 공격 이란?
    : 사용자가 인증된 상태에서 웹 어플리케이션에 악의적인 요청을 보내게 만드는 공격 기법 / 공격자는 사용자의 권한을 악용해 사용자가 의도하지 않은 요청을 보내도록 할 수 있다.


  1. 기본 로그인 페이지 없애기
 .formLogin().disable() // 기본 로그인 페이지 없애기
  • formLogin() : Spring Security의 기본 폼 기반 로그인 기능을 설정

  • 애플리케이션에서 커스텀 로그인 페이지를 사용하거나, 폼 기반 인증이 아닌 토큰 기반 인증 (JWT 등)을 사용하는 경우 유용


  1. header의 기본 설정 제한
  • frameOptions() : 브라우저의 X-Frame-Options 헤더를 설정하여 iframe 사용을 제한
  • 기본적으로 frameOptions가 활성화되어 있으면 브라우저가 해당 페이지를 다른 사이트의 iframe에서 로드하지 않도록 한다. 이를 비활성화하면, h2 콘솔과 같은 iframe을 사용하는 애플리케이션을 개발 중에 로드할 수 있게 해준다.



3. UserController에서 회원가입 시, 비밀번호 암호화하기

회원가입 시, 사용자로부터 입력받은 값 중에서 비밀번호를 Bean에 등록해놓은 passwordEncode.encode를 사용하여 비밀번호 암호화를 진행한다.

  private UserService userService;
    private UserInfoService userInfoService;
    private PasswordEncoder passwordEncoder; // Bean으로 등록해놓은 passwordEncoder 생성자 만들기

    public UserController(UserService userService, UserInfoService userInfoService, PasswordEncoder passwordEncoder) {
        this.userService = userService;
        this.userInfoService = userInfoService;
        this.passwordEncoder = passwordEncoder;
    }

@PostMapping("/signup")
    @Operation(summary = "사용자 회원가입", description = "회원가입을 합니다.")
    public ResponseEntity<String> signup(@RequestBody User user) {

        // user.getUserPassword()로 들어온 비밀번호를 encode로 암호화
        user.setUserPassword(passwordEncoder.encode(user.getUserPassword()));
        userService.signup(user);

        return new ResponseEntity<>("회원가입 성공", HttpStatus.OK);
    }
  • 회원가입 시, userPassword가 암호화되어 DB에 들어가는 것을 확인 할 수 있다.



2. User 로그인 기능 개발

  • 로그인 시, 입력된 비밀번호를 받아서 passwordEncoder.matches를 사용하여 암호화된 비밀번호와 일치하는지 확인한다.
@PostMapping("/login")
    @Operation(summary = "사용자 로그인 ", description = "로그인을 합니다.")
    public ResponseEntity<String> logIn(@RequestBody User user, HttpSession session) {
        User loginUser = null;
        if (user.getUserEmail() == null || user.getUserPassword() == null)
            return new ResponseEntity<>("입력 없음", HttpStatus.NOT_FOUND);
        // 입력된 이메일 날림
        User getUser = userService.searchByEmail(user.getUserEmail());
        // 아이디없음
        if (getUser == null) {
            return new ResponseEntity<>("아이디 틀림", HttpStatus.UNAUTHORIZED);
        }

        String encodePw = getUser.getUserPassword();
        if (passwordEncoder.matches(user.getUserPassword(), encodePw)) {

            loginUser = getUser;
            session.setAttribute("loginUser", loginUser);
            return new ResponseEntity<>("로그인 성공", HttpStatus.OK);
        }

        return new ResponseEntity<>("아이디 맞고, 비번 틀림", HttpStatus.UNAUTHORIZED);
    }

userEmail을 바탕으로 로그인 시 입력 받은 password와 DB에 저장되어 있는 encodePw 가 일치하는지 확인한다.


❗matches 사용 시, 파라미터 입력 순서가 중요하다!!

  • user.getUserPassword() : 사용자가 입력한 비밀번호
  • encodePw : DB에 저장된 비밀번호
passwordEncoder.matches(user.getUserPassword(), encodePw)



우선은 여기서 session에 저장하였던 로그인 유저의 정보를 JWT 토큰을 생성하여 토큰으로 통신을 하는 방식으로 수정하였다!!
곧 이 부분도 꼭 올려야지

참고)

https://january-diary.tistory.com/entry/SpringBoot-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EC%95%94%ED%98%B8%ED%99%94%ED%95%98%EA%B8%B0

'BackEnd > Spring Boot' 카테고리의 다른 글

[Spring Boot / Vue] 로그인 JWT 인증/인가 기능 구현  (2) 2024.11.20