4.8 KiB
4.8 KiB
title, source_type, status, related_branches, related_projects, tags, created, status_label, target_audience, inspiration_url, archive_url
| title | source_type | status | related_branches | related_projects | tags | created | status_label | target_audience | inspiration_url | archive_url | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| blog-topic / Spring Security 없이 application layer 에 method-level 인가 걸기 | blog-topic | raw |
|
|
|
2026-06-08 | ready-for-canonical | backend-engineer |
blog-topic: framework-free method authorization in Clean Architecture
Layer:
raw/blog-topics/— 구현에서 나온 블로그 글감 seed. canonical 추출은/ingest시 별도.
Parent / 부모
글감 한 줄
"@PreAuthorize 를 쓰면 application layer 가 Spring Security 에 결합된다. annotation 은 core 에, 집행은 adapter 에 두면 layer 순수성을 지키면서 method-level 인가를 걸 수 있다."
핵심 논지 / Outline
- 문제: Clean Architecture 에서 application/domain 은 framework-free 여야 하는데, Spring method security(
@PreAuthorize/@Secured)는 bean 을org.springframework.security에 결합시킨다. - 분리: 결정(decision) 과 메커니즘(mechanism) 분리.
- core:
@RequiresPermission(plain annotation) +AuthorizationPort(plain interface) +Permission(value object) +AuthorizationPrincipal(raw roles). - adapter:
AuthorizationManager<MethodInvocation>가 annotation 을 읽고 principal 을 매핑해 port 에 위임.@EnableMethodSecurity(prePostEnabled=false)+ customAdvisor(ROLE_INFRASTRUCTURE) 로 wiring.
- core:
- 거부 → 403 의 2-hop: core 가 자체 예외 throw → adapter 가 Spring
AccessDeniedException으로 변환 → 에러 envelope. - permission-centric RBAC: role=permission 묶음, registry 로 raw role→effective permission 해소(case-insensitive, fail-closed, no wildcard=least-privilege).
- 함정: CGLIB vs JDK proxy(concrete 주입 시
proxyTargetClass=true필수), AOP self-invocation bypass, unauthenticated(AuthenticationException) vs unauthorized(AccessDeniedException) 구분. → raw/errors/method-security-cglib-vs-jdk-proxy-usecase-injection-2026-06-08 - 마이그레이션 path: port interface 덕분에 RBAC→ABAC 전환이 구현체 교체로 끝남.
차별점
대부분의 Spring 튜토리얼은 @PreAuthorize 를 service 에 바로 붙인다. 이 글은 "왜 그게 hexagonal/clean 구조에서 부채인가 + 어떻게 분리하나"를 코드(TransactionPort 선례와 동일 패턴)로 보여준다.
트리거 / Trigger
- 트리거 유형:
branch-work - 트리거 날짜: 2026-06-08
- 트리거 연결 노트: raw/branch-notes/feature-authentication-authorization-contract
글감 / Topic seed
- 한 문장 요지: application layer에 Spring Security annotation을 직접 붙이지 않고 plain annotation + port + adapter method-security로 method-level authorization을 구현한다.
- 예상 제목 후보:
- Clean Architecture에서 framework-free method authorization 만들기
@PreAuthorize없이 application layer 인가 걸기
핵심 주장 후보 / Claim candidates
- 사실 후보:
- core annotation과 authorization port는 Spring Security type을 직접 의존하지 않는다.
- adapter가 Spring
AuthorizationManager와 advisor wiring을 소유한다.
- 의견/해석 후보:
- authorization decision과 framework mechanism을 분리하면 RBAC→ABAC migration path가 단순해진다.
Outline seed
@PreAuthorize가 application layer purity를 깨는 경로를 설명한다.- core annotation/port와 adapter enforcement를 분리한다.
- 403 envelope, CGLIB/JDK proxy, self-invocation bypass 한계를 적는다.
Canonical 전환 후보 / Canonical extraction candidates
wiki/projects/ca-tmpl/security-baseline-jwt-actuator-secrets.md후보:- framework-free method authorization 글감.
- 필요한 추가 검증:
- 현재
@RequiresPermission,AuthorizationPort, method security adapter 구현 여부.
- 현재
Sources / 근거 후보
- raw/branch-notes/feature-authentication-authorization-contract
- raw/errors/method-security-cglib-vs-jdk-proxy-usecase-injection-2026-06-08
미해결 / Unknown
- 아직 확인해야 할 사실: method security custom advisor의 현재 구현·검증 여부.
- 과장하면 안 되는 부분: Spring Security 자체를 부정하지 않고 ca-tmpl layer boundary 선택으로 제한한다.
Decision / 처리 결정
- 액션:
promote-to-canonical - 이유:
wiki/projects/ca-tmpl/security-baseline-jwt-actuator-secrets.md에 framework-free method authorization 글감으로 반영한다. - 다음 단계: blogify 전 구현 증거와 proxy/self-invocation 한계를 확인한다.