SpringBoot

SpringBoot - Spring Security로 비밀번호 암호화 (maven)

hminor 2024. 2. 19. 20:05

- pom.xml

<!-- Spring Security -->
    <!-- Spring Boot Starter Web 의존성 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

    <!-- Spring Boot Starter Security 의존성 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

 

- config.SecurityConfig
    아래 코드에선 모든 요청에 대해 접근을 우선 허용 (Swagger에 접근이 안되기에)
    그리고 비밀번호 암호화 코드는 passwordEncoder() 메서드를 참고

package com.server.login.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;


@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                // 모든 요청에 대해 접근 허용
                .anyRequest().permitAll()
                .and()
                .csrf().disable(); // CSRF 보호 비활성화 (Swagger UI를 사용할 때 편의를 위해)
    }

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

 

- service 
    passwordEncoder를 불러와서 선언

import org.springframework.security.crypto.password.PasswordEncoder;

private final PasswordEncoder passwordEncoder;

    이후 기존 입력한 비밀번호를 아래와 같이 하면 암호화 끝

String newPassword = passwordEncoder.encode(signupReqDto.getPassword())

   그리고 로그인 시 암호화로 저장한 비밀번호와 입력한 비밀번호가 같은지 확인하기 위해선
   아래와 같이 passwordEncoder.matchs(비밀번호1, 비밀번호2) 로 판단
    return 값은 true, false이기에 아래와 같이 작성하여 해결

// 로그인
@Transactional
public UserResDto login(LoginReqDto loginReqDto) {
    // 로그인 요청 DTO에서 아이디를 가져오기.
    String account = loginReqDto.getAccount();
    // 로그인 요청 DTO에서 비밀번호를 가져오기.
    String password = loginReqDto.getPassword();

    // userRepository에서 아이디로 사용자를 조회.
    UserEntity user = userRepository.findByAccount(account);

    // DB에서 가져온 사용자의 암호화된 비밀번호와 입력받은 비밀번호를 비교.
    if (!passwordEncoder.matches(password, user.getPassword())) {
        throw new RuntimeException("다시 확인해보세요!");
    }

    // 로그인 성공 시 사용자 정보를 반환.
    return UserResDto.fromEntity(user);
}

 


++ 추가

만약 특정 경로의 api만 접근을 허용하지 않도록 하려면 아래와 같이
.antMatchers().authenticated()에 경로를 넣어 인증을 하도록 하기.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            // Swagger UI 접근 허용
            .antMatchers("/swagger-ui.html", "/swagger-ui/**", "/v2/api-docs", "/v2/api-docs/**").permitAll()
            // "/user/**" 패턴에 대해서는 인증이 필요
            .antMatchers("/user/**").authenticated()
             // 나머지 요청에 대해서는 접근 허용
            .anyRequest().permitAll()
            .and()
            .csrf().disable(); // CSRF 보호 비활성화 (Swagger UI를 사용할 때 편의를 위해)
    }

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