보안을 위해 사용자 비밀번호를 암호화시켜서 DB에 저장하려고 했다.
해시 알고리즘은 임의의 길이의 데이터를 해싱처리 해 고정된 길이의 데이터로 매핑한다. 그러나 원문을 다시 만들어낼 수는 없다.
따라서 암호 보안에서는 암호를 해시 처리한 후 사용자 ID와 함께 짝을 지어 DB테이블에 보관한다. 로그인 시, 입력한 암호는 해시 처리되어 DB 테이블의 해시 처리된 입력값과 비교한다. 두 값이 일치한다면 사용자가 올바른 비밀번호를 입력한 것이다.
스프링에서는 비밀번호 암호화를 위해 제공하는 라이브러리가 있다. 지금 진행하는 프로젝트에서는 springboot를 사용하고 있으므로 이 라이브러리를 활용하기로 했다.
1. pom.xml
spring boot starter security를 추가한다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2. SecurityConfig
1. 클래스 위에 @Configuration, @EnableWebSecurity를 작성한다.
2. PasswordEncoder Bean을 만든다.
3. 이전 버전에는 WebSecurityConfigurerAdapter를 상속받아서 configure 메서드를 오버라이딩했지만 그 방식은 더 이상 사용되지 않는다. 따라서 SecurityFilterChain Bean을 만든다. cors, csrf를 방지하고 기본 로그인 페이지를 없앴다.
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.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@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();
}
}
3. UserServiceImpl
PasswordEncoder를 의존성 주입받아 사용한다.
1. 로그인 : 사용자가 아이디(=이메일), 비밀번호를 입력하면 userInfo에서 가져온 암호화 비밀번호와 지금 입력받은 비밀번호가 일치하는지 passwordEncoder.matches(암호화텍스트, 입력텍스트)로 확인한다. 일치한다면 dto 비밀번호를 암호화된 비밀번호로 변경하고 로그인한다.
2. 회원가입 : 사용자가 입력한 비밀번호를 인코딩한 후 dto 비밀번호 정보를 변경한다. 그 뒤 회원가입한다.
3. 정보 수정 : 사용자가 비밀번호를 변경하고자 한다면(userpw != null) 새 비밀번호를 인코딩한 뒤 dto 비밀번호 정보를 변경한다. 그 뒤 정보수정을 진행한다.
@Autowired
private PasswordEncoder passwordEncoder;
//생략
@Override
public User login(User userDto) throws Exception {
if(userDto.getUseremail() == null || userDto.getUserpw() == null)
return null;
return userMapper.login(userDto);
//userInfo에서 가져온 비밀번호(암호화됨)와 지금 입력받은 비밀번호 match 확인
String encodePw = userMapper.userInfo(userDto.getUseremail()).getUserpw();
if(passwordEncoder.matches(userDto.getUserpw(),encodePw)) {
//암호화 된 비밀번호로 pw 정보 변경 후 로그인
userDto.setUserpw(encodePw);
return userMapper.login(userDto);
}else {
return null;
}
}
@Override
public int register(User userDto) throws Exception {
//비밀번호 인코딩 후 회원가입
userDto.setUserpw(passwordEncoder.encode(userDto.getUserpw()));
return userMapper.register(userDto);
}
@Override
public int modify(User userDto) throws Exception {
//dto 비밀번호가 null값이 아니라면 인코딩해서 새로 저장
if(userDto.getUserpw() != null) userDto.setUserpw(passwordEncoder.encode(userDto.getUserpw()));
return userMapper.modify(userDto);
}
'기록 > BACKEND' 카테고리의 다른 글
[SpringBoot] JPA repository로 ManyToOne관계 쿼리 작성 (0) | 2022.08.02 |
---|---|
[SpringBoot] JWT토큰 인터셉터 처리하기 (0) | 2022.07.30 |
[SpringBoot] 자바 메일 보내기 (0) | 2022.07.21 |
[SpringBoot] 따로 개발한 springboot와 vue 합치기 (0) | 2022.06.29 |
[SpringBoot] Swagger 3.x 적용 (0) | 2022.05.10 |
댓글