상세 컨텐츠

본문 제목

SpringBoot MSA (10) - MicroService / UserService 비밀번호 암호화 (3)

Spring/SpringBoot-MSA

by ChrisMare 2023. 10. 17. 11:32

본문

기존 UserService에서 비밀번호 암호화를 하지않았다.

 

Spring Security ( Authentication + Authorization ) 을 사용하여 진행하겠습니다.

Authentication: 인증

Authorization: 권한

위 두가지를 하기위해서

1. Spring security jar를 dependency에 추가

2. WebSecurityConfigurerAdapter를 상속받는 Security Configuration 빈클래스 생성

3. Security Configuration 클래스에 @EnableWebSecurity 추가

4. Authentication -> configure(AuthenticationManagerBuilder auth) 메서드를 재정의

5. Password encode 를 위한 BCryptPasswordEncoder 빈 정의

6. Authrization -> configure(HttpSecurity http) 메서드를 재정의

 

pom.xml

> security jar 추가

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

 

security > WebSecurity.java

package com.example.userservice.security;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity //WebSecurity를 사용하겠다는 의미 우선순위가 높다
public class WebSecurity extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // csrf 사이트간 위조요청
        http.csrf().disable();
        http.authorizeRequests().antMatchers("/users/**").permitAll();
    }
}

 

위 작업 후 서버 재실행 시 콘솔에 사용되어질 security password가 나오게 됩니다.

하지만 /users로 시작하는 url이 아니라면 오류가 되는 것을 볼 수 있다.

해당 부분의 프레임 옵션들을 비활성화 해줘야된다.

옵션 추가

security > WebSecurity.java

package com.example.userservice.security;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity //WebSecurity를 사용하겠다는 의미 우선순위가 높다
public class WebSecurity extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // csrf 사이트간 위조요청
        http.csrf().disable();
        http.authorizeRequests().antMatchers("/users/**").permitAll();

        http.headers().frameOptions().disable();
    }
}

 

이제 h2-console에 정상 접속된다.

 

이제 회원가입전 비밀번호 암호화작업을 진행하겠습니다.

 

service > UserServiceImpl.java

BCryptPasswordEncoder 를 사용하여 진행하겠습니다.

BCryptPasswordEncoder 생성자 주입

BCryptPasswordEncoder passwordEncoder;

@Autowired
public UserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder) {
    this.userRepository = userRepository;
    this.passwordEncoder = passwordEncoder;
}

하지만 BCryptPasswordEncoder는 빈을 등록하지 않았기 때문에 오류가 발생합니다.

가장 먼저 실행되는 메소드 SpringBootApplication에 가서 BCryptPasswordEncoder에 대한 Bean을 등록해줘야 합니다.

타입을 같게 해서 등록하기만 하면 됩니다.

 

UserServiceApplication.java

package com.example.userservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {

    public static void main(String[] args) {
       SpringApplication.run(UserServiceApplication.class, args);
    }

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

}

 

service > UserServiceImpl.java > createUser 의 암호화 작업 진행

userEntity.setEncryptedPwd(passwordEncoder.encode(userDto.getPwd())); //암호화 처리

service > UserServiceImpl.java

package com.example.userservice.service;

import com.example.userservice.dto.UserDto;
import com.example.userservice.repository.UserEntity;
import com.example.userservice.repository.UserRepository;
import com.netflix.discovery.converters.Auto;
import org.dom4j.rule.Mode;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import org.modelmapper.spi.MatchingStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.UUID;

@Service
public class UserServiceImpl implements UserService {

    UserRepository userRepository;
    BCryptPasswordEncoder passwordEncoder;

    @Autowired
    public UserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public UserDto createUser(UserDto userDto) {
        userDto.setUserId(UUID.randomUUID().toString());

        ModelMapper mapper = new ModelMapper();
        // 딱 맞는 경우에만 지정되도록
        mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        UserEntity userEntity = mapper.map(userDto, UserEntity.class);

        userEntity.setEncryptedPwd(passwordEncoder.encode(userDto.getPwd())); //암호화 처리


        // jpa로 저장
        userRepository.save(userEntity);

        UserDto returnUserDto = mapper.map(userEntity, UserDto.class);

        return returnUserDto;
    }

}

 

실행해서 암호화 작업이 되었는지 확인하겠습니다.

h2-console에서 들어간 정보 확인

앞의 게시글과는 다르게 비밀번호 암호화가 적용되어진것을 볼 수 있습니다.

관련글 더보기

댓글 영역