95 lines
11 KiB
Markdown
95 lines
11 KiB
Markdown
---
|
||
title: official-doc / Spring Security — Method Security (@PreAuthorize/@PostAuthorize + Unannotated-Method Backstop)
|
||
source_type: official-doc
|
||
url: https://docs.spring.io/spring-security/reference/servlet/authorization/method-security.html
|
||
archive_url:
|
||
related_branches: [feature-keycloak-spring-rs-role-mapping]
|
||
related_projects: [keycloak-patterns]
|
||
tags: [official-doc, keycloak-patterns, auth, spring-security]
|
||
created: 2026-07-18
|
||
---
|
||
|
||
# Spring Security — Method Security (@PreAuthorize / @PostAuthorize / SpEL / Unannotated-Method Backstop)
|
||
|
||
> Layer: `raw/official-docs/` — Spring Security Reference `servlet/authorization/method-security.html` 페이지의 verbatim 발췌.
|
||
> `feature-keycloak-spring-rs-role-mapping` 의 RBAC enforcement location **Alternative B**(method-level security — `@EnableMethodSecurity` + `@PreAuthorize("hasRole('admin-role')")`) 결정의 1차 근거. locality(보호 코드 옆에 규칙) + SpEL expressiveness(파라미터/리턴값) 뿐 아니라, **unannotated method 는 보호되지 않는다는 벤더 자신의 CRITICAL 경고 + catch-all `HttpSecurity` 규칙 지침**을 grounding 하기 위해 별도 보관.
|
||
|
||
## Parent / 활용 branch
|
||
|
||
| Branch | 이 자료가 정당화하는 결정 |
|
||
|---|---|
|
||
| [[raw/branch-notes/feature-keycloak-spring-rs-role-mapping]] | RBAC enforcement location Alternative B — `@EnableMethodSecurity` + `@PreAuthorize("hasRole('admin-role')")` 채택의 근거(활성화 방법 + SpEL 파라미터/리턴값 표현력). 동시에 **unannotated method 는 보호 안 됨 → catch-all `HttpSecurity` 규칙 필수**라는 벤더 backstop 경고를 명시적으로 grounding |
|
||
|
||
## 출처 / Source
|
||
|
||
- 원본 URL: https://docs.spring.io/spring-security/reference/servlet/authorization/method-security.html
|
||
- 아카이브 URL: (미수집)
|
||
- 저자 / 조직: Spring Security (Broadcom / Spring team)
|
||
- 발행일: rolling reference docs (버전 번호는 이 페이지 발췌 범위에 명시되지 않음)
|
||
- 마지막 확인일: 2026-07-18
|
||
|
||
## 왜 저장했는지 / Why archived
|
||
|
||
Method-level security(`@EnableMethodSecurity` + `@PreAuthorize`)를 채택하려는 결정은 (1) 활성화 방법과 SpEL 문법 근거뿐 아니라 (2) **"annotation 이 없는 메서드는 보호되지 않는다"는 벤더의 명시적 경고**를 함께 가지고 있어야 안전하게 채택 가능하다. 이 경고가 곧 method-only 전략의 backstop 요구사항(HttpSecurity catch-all rule)의 1차 근거이므로, 형제 문서 [[raw/official-docs/spring-security-authorization-defense-in-depth]](request+method 동시 사용을 다루는 개요 페이지)와 별도로 이 세부 메커니즘 페이지를 발췌 보관.
|
||
|
||
## 핵심 인용 / Key quotes (verbatim)
|
||
|
||
> [§Method Security] "You can activate it in your application by annotating any @Configuration class with @EnableMethodSecurity or adding <method-security> to any XML configuration file, like so:"
|
||
|
||
> [§Authorizing Method Invocation with @PreAuthorize] "This is meant to indicate that the method can only be invoked if the provided expression hasRole('ADMIN') passes."
|
||
|
||
> [§Using Method Parameters] "Additionally, Spring Security provides a mechanism for discovering method parameters so they can also be accessed in the SpEL expression as well."
|
||
|
||
> [§Method authorization is a combination of before- and after-method authorization] (code example, verbatim, contiguous lines):
|
||
> ```
|
||
> @Service
|
||
> public class MyCustomerService {
|
||
> @PreAuthorize("hasAuthority('permission:read')")
|
||
> @PostAuthorize("returnObject.owner == authentication.name")
|
||
> public Customer readCustomer(String id) { ... }
|
||
> }
|
||
> ```
|
||
|
||
> [§Comparing Request-Level Authorization to Method-Level Authorization] "It's important to remember that when you use annotation-based Method Security, then unannotated methods are not secured.
|
||
> To protect against this, declare a catch-all authorization rule in your HttpSecurity instance."
|
||
|
||
> [보충 — Method Security 개요] "Spring Boot Starter Security does not activate method-level authorization by default."
|
||
|
||
## Claims Extracted / 추출된 주장
|
||
|
||
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|
||
|---|---|---|---|---|---|
|
||
| SPRING-MS-C1 | Method security 는 `@Configuration` 클래스에 `@EnableMethodSecurity` 를 붙이거나(또는 XML `<method-security/>`) 활성화하며, 이후 `@PreAuthorize`/`@PostAuthorize`/`@PreFilter`/`@PostFilter` 로 method invocation(파라미터·리턴값 포함)을 authorize 할 수 있다 | [§Method Security] "You can activate it in your application by annotating any @Configuration class with @EnableMethodSecurity or adding <method-security> to any XML configuration file, like so:" | `official-vendor-doc` | Spring Security 6.x/7.x reference, Servlet 환경 | `@EnableMethodSecurity` 가 Spring Boot 자동설정에 포함된다는 것은 증명 안 함(오히려 반대 — 아래 SPRING-MS-C5 참조) |
|
||
| SPRING-MS-C2 | `@PreAuthorize` 는 SpEL 표현식(예: `hasRole('ADMIN')`)이 참일 때만 메서드가 실제로 호출되는 **사전(before-invocation)** 인가 체크다 | [§Authorizing Method Invocation with @PreAuthorize] "This is meant to indicate that the method can only be invoked if the provided expression hasRole('ADMIN') passes." | `official-vendor-doc` | `@EnableMethodSecurity` 가 켜진 Spring-managed bean 의 모든 메서드 | request-level(`authorizeHttpRequests`) 규칙과의 평가 순서·우선순위는 이 페이지 범위 밖 |
|
||
| SPRING-MS-C3 | SpEL 표현식은 method **parameter**(`@P`, Spring Data `@Param`, `-parameters` 컴파일 플래그, 또는 bytecode debug symbol 로 discovery)를 참조할 수 있다 | [§Using Method Parameters] "Additionally, Spring Security provides a mechanism for discovering method parameters so they can also be accessed in the SpEL expression as well." | `official-vendor-doc` | `hasPermission(#c, 'write')` 류 파라미터 기반 인가 결정 | 파라미터 discovery 순서(4가지 방법)의 우선순위 세부는 별도 발췌 필요 — 이 claim 은 "가능하다"만 보증 |
|
||
| SPRING-MS-C4 | `@PreAuthorize`(사전 체크)와 `@PostAuthorize`(사후 체크, `returnObject` SpEL 변수로 **리턴값** 접근 가능)를 같은 메서드에 함께 선언할 수 있으며, 예시로 `returnObject.owner == authentication.name` 이 제시된다 | 코드 예시(§ Method authorization is a combination of before- and after-method authorization): `@PreAuthorize("hasAuthority('permission:read')")` / `@PostAuthorize("returnObject.owner == authentication.name")` / `public Customer readCustomer(String id) { ... }` | `official-vendor-doc` | 리턴값 기반(예: ownership 검증) 인가 결정 — IDOR(Insecure Direct Object Reference) 방어 패턴 | `PermissionEvaluator`/`hasPermission` 기반 object-level ACL 전체 인프라까지 이 인용이 증명하지는 않음(별도 섹션) |
|
||
| SPRING-MS-C5 (CRITICAL — backstop) | **Annotation 기반 Method Security 를 쓸 때 annotation 이 없는 메서드는 보호되지 않는다.** 이를 막기 위해 `HttpSecurity` 인스턴스에 catch-all authorization 규칙을 선언하라고 명시적으로 지시한다. 별도로 "Spring Boot Starter Security 는 method-level authorization 을 기본으로 활성화하지 않는다"고도 명시한다 | [§Comparing Request-Level Authorization to Method-Level Authorization] "It's important to remember that when you use annotation-based Method Security, then unannotated methods are not secured. To protect against this, declare a catch-all authorization rule in your HttpSecurity instance." + "Spring Boot Starter Security does not activate method-level authorization by default." | `official-vendor-doc` | method-only(`@PreAuthorize` 단독) RBAC 전략을 채택하는 모든 코드베이스 — Alternative B 의 backstop 요구사항 직접 근거 | catch-all 규칙의 **정확한 shape**(예: `anyRequest().authenticated()` vs 더 세밀한 matcher)는 지정하지 않음 — "declare a catch-all rule" 만 지시, 구체 구현은 별도 결정 필요 |
|
||
|
||
## Usage Boundaries / 적용 경계
|
||
|
||
- 이 자료가 직접 증명하는 것:
|
||
- `SPRING-MS-C1`: `@EnableMethodSecurity` 활성화 방법 + 이후 사용 가능한 4개 annotation
|
||
- `SPRING-MS-C2`: `@PreAuthorize` 의 사전 체크 SpEL 시맨틱
|
||
- `SPRING-MS-C3`: SpEL 이 method parameter 를 참조할 수 있음(discovery 메커니즘 존재)
|
||
- `SPRING-MS-C4`: SpEL 이 method 리턴값(`returnObject`)을 참조할 수 있음(`@PostAuthorize` 조합)
|
||
- `SPRING-MS-C5`: unannotated method 는 method security 로 보호되지 않으며, 벤더가 HttpSecurity catch-all 규칙을 명시적으로 요구함 + Boot Starter Security 는 method security 를 기본 비활성 상태로 둠
|
||
- 이 자료가 증명하지 않는 것:
|
||
- method-level 과 request-level 규칙이 동시에 걸렸을 때의 정확한 평가 순서/충돌 처리(그건 [[raw/official-docs/spring-security-authorization-architecture]] 류의 별도 페이지 몫)
|
||
- catch-all `HttpSecurity` 규칙의 구체적 matcher 모양 — "선언하라"는 지시만 있고 정확한 DSL 코드는 이 문서가 예시로 보여주는 한 형태(`anyRequest().authenticated()`)일 뿐, 그것이 **유일한** 정답이라는 것은 증명 안 함
|
||
- `feature-keycloak-spring-rs-role-mapping` 의 실제 `admin-role` naming, `JwtAuthenticationConverter` 매핑 등 프로젝트 구체 구현의 정확성 — 그건 [[raw/official-docs/spring-security-resource-server-jwt]] 의 몫
|
||
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
|
||
- P3A 실제 구현에서 `SecurityFilterChain` 에 catch-all `anyRequest().authenticated()` 를 실제로 선언했는지, 그리고 `@PreAuthorize` 가 없는 다른 엔드포인트가 실제로 열려 있지 않은지 로컬 curl 검증 필요
|
||
- `@EnableMethodSecurity` 를 명시적으로 켰는지(Boot Starter Security 기본 비활성이므로) 로컬 설정 확인 필요
|
||
|
||
## 메모 / Notes
|
||
|
||
- 이 페이지는 형제 문서 [[raw/official-docs/spring-security-authorization-defense-in-depth]] (Alternative C — request+method 동시 사용 개요)가 예고했던 "하위 세부 페이지" 중 하나(`servlet/authorization/method-security.html`)다. 개요 페이지는 "defense in depth" 프레이밍만 제공하고, 이 페이지가 그 defense-in-depth 가 **왜 필요한지**(unannotated method 미보호)의 구체 메커니즘 근거를 제공한다.
|
||
- SPRING-MS-C5 의 인용 원문은 컬리 어포스트로피(`It's` → `It’s`, U+2019)를 사용한다 — 발췌 시 원문 그대로 보존.
|
||
- 추가로 봐야 할 동일 출처 페이지: `servlet/authorization/authorize-http-requests.html` (request-level DSL 세부), `servlet/architecture.html` (AuthorizationManager 아키텍처).
|
||
|
||
## Related / 관련
|
||
|
||
- [[raw/official-docs/spring-security-authorization-defense-in-depth]] — request-based + method-based 조합을 "defense in depth" 로 명명한 상위 개요 페이지 (Alternative C 근거)
|
||
- [[raw/official-docs/spring-security-authorization-architecture]] — `AuthorizationManager` / method security 세부 아키텍처 근거
|
||
- [[raw/official-docs/spring-security-resource-server-jwt]] — JWT 인증 + authority mapping (같은 branch 의 authN 근거)
|