업뎃(2024.04)
참고링크 : WebSecurityConfigurerAdapter 지원 중단
Users Microservice - Spring Security 연동
Spring Security는 Authentication(인증)과 Authorization(권한)과 관련된 작업을 처리할 수 있도록 해준다.
💡 인증(Authentication), 권한(Authorization)
💡 인증(Authentication)
사용자나 시스템이 자신이 주장하는 신원을 확인하는 프로세스
사용자가 시스템에 로그인하거나 특정 서비스에 액세스하기 위해 자격 증명(예: 아이디와 비밀번호)를 제공하는 것
💡 권한(Authorization)
적절한 인증이 통과되었을 때 할 수 있는 작업들이 어떤 것들이 있는가
통과가 안되었을 때 리소스를 차단한다 등
애플리케이션에 spring secutiry jar를 Dependency에 추가
- maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- gradle
implementation 'org.springframework.boot:spring-boot-starter-security'
webSercurityConfigurerAdapter를 상속받는 Secutiry Configuration 클래스 생성
Websecurity 클래스 생성
Secutiry Configuration 클래스에 @EnableWebSecurity 추가
webSercurityConfigurerAdapter상속 받아서 Override하기(윈도우: alt + ins)
@Configuration // 다른 빈들보다 먼저 추가
@EnableWebSecurity // WebSecurity 용도이다
public class WebSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable(); // csrf 사용하지 않겠다.
http.authorizeRequests().antMatchers("/users/**").permitAll(); // authorize Requests허용할 수 있는 작업은 "/users/**"에 Match되면 PermitAll해라
}
}
서버 실행해보자
스프링 시큐리티 라이브러리를 추가하게 되면 security password가 표시된다.
지금 당장은 사용하지 않지만, 나중에 스프링 부트 프로젝트 인증 작업을 하기 위해서 특별하게 암호와 아이디, 패스워드를 지정하지 않은 상태에서는 여기에 출력되는 security password를 사용해서 인증 작업을 처리할 수도 있다.
잘 작동되고 있다.
h2-console에 들어가보면 오류가 뜬다.
오류가 뜨는 원인은 각각의 h2라는 데이터베이스에 프레임으로 데이터가 나눠져 있기 때문이다.(❓)
Authentication -> configure(AuhenticationManagerBuilder auth) 메서드를 재정의
오류가 안뜨도록 무시하는 설정을 해주자.
@Configuration // 다른 빈들보다 먼저 추가
@EnableWebSecurity // WebSecurity 용도이다
public class WebSecurity extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable(); // csrf 사용하지 않겠다.
http.authorizeRequests().antMatchers("/users/**").permitAll(); // authorize Requests허용할 수 있는 작업은 "/users/**"에 Match되면 PermitAll해라
// ✔ 여기 추가!
http.headers().frameOptions().disable(); // 헤더의 프레임옵션을 사용하지 않겠다
}
}
비밀번호 암호화
💡 BCryptPasswordEncoder
- 사용패스워드를 해싱하기 위해 Bcrypt 알고리즘 사용
- Bcrypt 알고리즘 사용하게 되면 랜덤 Salt를 부여하여 여러 번 hash를 적용한 암호화 방식을 사용
service createUser() 수정
기존 UserRepository를 필드 주입 방식으로 주입했는데 생성자 주입 방식으로 변경하고,
BCryptPasswordEncoder 객체도 마찬가지로 생성자 주입 방식으로 의존성을 주입한다.
UserRepository userRepository;
BCryptPasswordEncoder passwordEncoder;
@Autowired
public UserServiceImpl(UserRepository userRepository, BCryptPasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
그런데 생성자의 passwordEncoder의 매개변수에서 계속 빨간줄(에러)이 뜬다. 에러 메시지는 'Could not autowire. No beans of 'BCryptPasswordEncoder' type found. '인데 Autowire를 사용할 수 없고, BCryptPasswordEncoder라는 bean을 찾을 수 없다는 뜻이다.
Autowire는 Spring 컨텍스트가 기동되면서 자동으로 등록할 수 있는 빈을 찾아서 메모리에 객체를 생성해주는 것이다.(자동으로 빈을 등록해준다.)
해결 ▶
가장 먼저 호출되는 Application의 클래스(UserServiceApplication)에 빈을 넣어놓으면 된다.
빈을 넣어두면 인스턴스 타입이 같은 것을 가져와서 주입해준다.(오류 해결~)
Password encode를 위한 BCryptPasswordEncoder 빈 정의
UserServiceApplication
BCryptPasswordEncoder을 @Bean에 추가해준다.
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
UserServiceImpl
service createUser() 암호화 적용
@Override
public UserDto createUser(UserDto userDto) {
userDto.setUserId(UUID.randomUUID().toString());
//UserDto -> UserEntity 변환 작업
ModelMapper mapper = new ModelMapper();
mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
UserEntity userEntity = mapper.map(userDto, UserEntity.class);
userEntity.setEncryptedPwd(passwordEncoder.encode(userDto.getPwd())); //✔여기
userRepository.save(userEntity);
UserDto returnUserDto = mapper.map(userEntity, UserDto.class);
return returnUserDto;
}
서버 재실행 후 포스트맨으로 post하고, DB 확인
같은 패스워드로 지정했음에도 DB에는 암호화되어 저장되었다.
👀 참고(gradle, SprongBoot 3.x 버전)
참고 - gradle로 security할 경우
참고 - SpringBoot 3점대 버전 Spring Security 설정