스프링 시큐리티 : @Secured , @PreAuthorized, @PostAuthorized

이진욱·2024년 12월 19일

이론

목록 보기
13/24

1. @Secured

@Secured는 역할(Role) 기반으로 접근을 제어합니다. 주로 특정 메서드에 대해 특정 역할(예: ROLE_ADMIN, ROLE_USER)을 요구할 때 사용됩니다.

@Service
public class SampleService {

    @Secured("ROLE_ADMIN")
    public String adminOnlyMethod() {
        return "This method is accessible only to ADMIN users.";
    }

    @Secured({"ROLE_USER", "ROLE_MANAGER"})
    public String userAndManagerMethod() {
        return "This method is accessible to USER and MANAGER roles.";
    }
}

설명

  • @Secured("ROLE_ADMIN"): 메서드 호출 전에 사용자 역할을 검사합니다. ROLE_ADMIN이 없으면 예외를 발생시킵니다.
  • 다중 역할 지정: @Secured({"ROLE_USER", "ROLE_MANAGER"}).

한계

단순히 역할(Role)만 검사할 수 있으며, 동적인 조건(예: 사용자 이름, 상태 등)을 사용할 수 없습니다.

2. @PreAuthorize 예제

@PreAuthorize는 SpEL(Spring Expression Language)을 사용하여 더욱 유연한 조건을 정의할 수 있습니다.
역할(Role)뿐만 아니라, 사용자 속성이나 동적 조건에 따라 접근을 제어할 수 있습니다.

@Service
public class SampleService {

    // 단순 역할 기반
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public String adminOnlyMethod() {
        return "This method is accessible only to ADMIN users.";
    }

    // 다중 역할 기반
    @PreAuthorize("hasAnyRole('ROLE_USER', 'ROLE_MANAGER')")
    public String userAndManagerMethod() {
        return "This method is accessible to USER and MANAGER roles.";
    }

    // 사용자 이름에 따라 제어
    @PreAuthorize("#username == authentication.name")
    public String methodForSpecificUser(String username) {
        return "This method is accessible only to the logged-in user with matching username.";
    }

    // 사용자 권한과 속성을 복합적으로 검사
    @PreAuthorize("hasRole('ROLE_USER') and #id == authentication.principal.id")
    public String methodForUserWithMatchingId(Long id) {
        return "This method is accessible only if the logged-in user has ROLE_USER and matching ID.";
    }
}

설명

  • hasRole('ROLE_ADMIN'): 단순 역할 검사.
  • hasAnyRole('ROLE_USER', 'ROLE_MANAGER'): 다중 역할 검사.
  • #username == authentication.name: 입력 파라미터(#username)가 현재 인증된 사용자의 이름(authentication.name)과 같아야 합니다.
  • #id == authentication.principal.id: 입력된 ID가 인증된 사용자의 ID와 같아야 합니다.

비교

결론

단순 역할 검사: @Secured 사용 (가볍고 직관적).
복합 조건 검사: @PreAuthorize 사용 (유연하고 강력한 조건 정의 가능).

3. @PostAuthorized

@PostAuthorize는 Spring Security에서 메서드 실행 후 권한을 검사하는 데 사용하는 애노테이션입니다. 주로 반환된 데이터에 대해 권한 검사를 수행하는 경우에 사용됩니다. 이를 통해 사용자가 메서드 호출 결과를 볼 수 있는 권한이 있는지 확인할 수 있습니다.

주요 특징

  • 메서드 실행 후 권한 검사

    • 메서드가 실행되고 결과가 반환된 이후에 권한을 검사합니다.
    • 반환된 객체나 데이터를 기반으로 접근 권한을 설정할 수 있습니다.
  • SpEL (Spring Expression Language) 사용

    • 권한 검사를 위해 SpEL 표현식을 사용합니다.
    • 반환값을 returnObject로 참조할 수 있습니다.

예제

@PostAuthorize("hasRole('ADMIN') or returnObject.owner == authentication.name")
public SomeEntity findById(Long id) {
// 메서드 로직
return someEntity;
}

  • hasRole('ADMIN'): 사용자에게 ADMIN 역할이 있는지 확인.
  • returnObject.owner == authentication.name: 반환된 객체(returnObject)의 owner 속성이 현재 인증된 사용자 이름과 동일한지 확인.
1. 반환된 데이터에 따라 권한을 검사
@PostAuthorize("returnObject.createdBy == authentication.name")
public Document getDocumentById(Long id) {
    Document document = documentRepository.findById(id).orElseThrow();
    return document;
}
  • 사용자가 Document 객체의 작성자(createdBy)와 동일한 경우에만 데이터를 반환.
2. 특정 역할 기반으로 접근 제한
@PostAuthorize("hasRole('MANAGER')")
public List<User> getAllUsers() {
    return userService.findAll();
}
  • MANAGER 역할을 가진 사용자만 반환된 사용자 목록에 접근 가능.

주의사항

  • 메서드 실행 후 동작

권한 검사는 메서드 실행 후에 수행되므로, 메서드가 실행되는 것을 사전에 차단할 수 없습니다. 이를 위해서는 @PreAuthorize를 사용해야 합니다.

  • 성능 이슈

반환된 데이터를 기반으로 권한 검사를 수행하므로, 대량 데이터 반환 시 성능에 영향을 미칠 수 있습니다.

  • 복잡한 SpEL 표현식

SpEL 표현식이 복잡해지면 유지보수가 어려워질 수 있으므로 간단하게 유지하는 것이 좋습니다.

profile
열심히 하는 신입 개발자

0개의 댓글