api에 접근을 제어하기 위해 Controller에 userDetails로 받아온 유저의 권한을 확인하는 로직이 필요하다.
나는 그 기능을 userDetails에서 userRole을 받아와 조건문으로 권한이 일치하는지 확인하는 코드를 작성했었는데
// CategoryController
@PostMapping
public ResponseEntity<Void> createCategory(@RequestBody CategoryCreateRequestDto categoryCreateRequestDto,
@AuthenticationPrincipal UserDetailsImpl userDetails) {
// 사실 이 if문의 조건부도 가독성이 많이 떨어진다...
if (!userDetails.hasRole(UserRole.MASTER) && !userDetails.hasRole(UserRole.MANAGER)) {
throw new CustomException(ErrorCode.ACCESS_DENIED);
}
categoryService.createCategory(categoryCreateRequestDto);
return new ResponseEntity<>(HttpStatus.CREATED);
}
// UserDetailsImpl
public boolean hasRole(UserRole role) {
return this.userRole == role;
}
프로젝트 팀원분이 @Secured
어노테이션에 대해 알려주어서 알아보게되었다.
방법은 정말 간단한데
우선 security 환경 설정을 구성하는 SecurityConfig 클래스에 @EnableMethodSecurity(securedEnabled = true)
어노테이션을 활성화해준다.
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfig {
// ...
}
그리고 다시 Controller로 돌아가서 @Secured
어노테이션과 뒤에 권한을 설정할 enum값을 추가하고,
이제 필요없는 userDetails와 if문을 지우면 끝이다.
@PostMapping
@Secured({"MASTER", "MANAGER"})
public ResponseEntity<Void> createCategory(@RequestBody CategoryCreateRequestDto categoryCreateRequestDto) {
categoryService.createCategory(categoryCreateRequestDto);
return new ResponseEntity<>(HttpStatus.CREATED);
}
코드가 엄청나게 가벼워지고 테스트해본 결과 기능도 정상적으로 작동하는 것을 확인할 수 있었다.