'WebSecurityConfigurerAdapter' is deprecated
Spring Security 5.7.0부터 WebSecurityConfigurerAdapter가 deprecated 되었다고 한다. WebSecurityConfigurerAdapter를 상속받는 대신 SecurityFilterChain을 @Bean으로 등록하는 방식으로 변경했다.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
// 나머지 설정...
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
// 나머지 설정...
return http.build();
}
}
Public Key Retrieval is not allowed
org.hibernate.exception.JDBCConnectionException: unable to obtain isolated JDBC connection [Public Key Retrieval is not allowed] [n/a]
MySQL 8.0 이상 버전에서는 보안 강화를 위해 RSA 공개 키를 사용하여 비밀번호를 암호화하는 기능이 기본적으로 활성화되어 있다고 한다. 이 기능을 사용하기 위해서는 JDBC URL에 명시적으로 allowPublicKeyRetrieval=true 옵션을 추가해야 한다고.
spring:
datasource:
url: jdbc:mysql://localhost:3306/reservation_db?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8
spring:
datasource:
url: jdbc:mysql://localhost:3306/reservation_db?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8&allowPublicKeyRetrieval=true
Access denied for user 'root'@'192.168.65.1' (using password: YES)
org.hibernate.exception.GenericJDBCException: unable to obtain isolated JDBC connection
수강 중인 강의 프로젝트에서 3306 포트를 이미 사용하고 있어서 Docker Compose 설정할 때 MySQL 컨테이너의 내부 포트(3306)를 호스트의 3307 포트로 매핑했었는데, 애플리케이션 설정할 때 3306 포트로 접속을 시도하고 있었다. application.yml 파일의 데이터베이스 연결 URL에서 포트를 3306에서 3307로 변경하여 Docker 컨테이너의 포트 매핑과 일치시켰다.
services:
mysql:
ports:
- "3307:3306" # 호스트의 3307 포트를 컨테이너의 3306 포트로 매핑
spring:
datasource:
url: jdbc:mysql://localhost:3306/reservation_db?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8&allowPublicKeyRetrieval=true
spring:
datasource:
url: jdbc:mysql://localhost:3307/reservation_db?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8&allowPublicKeyRetrieval=true
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
/**
* 일반 사용자 회원가입 API
* @param request 회원가입 요청 정보
* @return 회원가입 결과 응답
*/
@PostMapping("/signup")
public ResponseEntity<ApiResponse<UserDto.SignUpResponse>> signUp(
@Valid @RequestBody UserDto.SignUpRequest request) {
UserDto.SignUpResponse response = userService.signUp(request);
return ResponseEntity.status(HttpStatus.CREATED)
.body(ApiResponse.success("회원가입이 성공적으로 완료되었습니다.", response));
}
}
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
/**
* 일반 사용자 회원가입 처리 메서드
* @param request 회원가입 요청 정보
* @return 회원가입 결과 정보
*/
@Transactional
public UserDto.SignUpResponse signUp(UserDto.SignUpRequest request) {
// 이메일 중복 확인
if (userRepository.existsByEmail(request.getEmail())) {
throw new CustomException(ErrorCode.EMAIL_ALREADY_EXISTS);
}
// 전화번호 중복 확인
if (userRepository.existsByPhone(request.getPhone())) {
throw new CustomException(ErrorCode.PHONE_ALREADY_EXISTS);
}
// 사용자 객체 생성 및 저장
User user = User.builder()
.email(request.getEmail())
.password(passwordEncoder.encode(request.getPassword())) // 비밀번호 암호화
.name(request.getName())
.phone(request.getPhone())
.role(UserRole.ROLE_USER) // 일반 사용자 권한 설정
.active(true) // 기본적으로 활성화 상태로 설정
.build();
// DB에 저장
User savedUser = userRepository.save(user);
// 응답 객체 생성 및 반환
return UserDto.SignUpResponse.builder()
.userId(savedUser.getId())
.email(savedUser.getEmail())
.name(savedUser.getName())
.phone(savedUser.getPhone())
.role(savedUser.getRole())
.build();
}
}
