Skip to content

[FEAT/#359] 백오피스 권한 처리 및 Security 세팅#360

Merged
2ghrms merged 20 commits into
developfrom
feat/#359-admin-api-authorization
Jun 23, 2026
Merged

[FEAT/#359] 백오피스 권한 처리 및 Security 세팅#360
2ghrms merged 20 commits into
developfrom
feat/#359-admin-api-authorization

Conversation

@2ghrms

@2ghrms 2ghrms commented Jun 22, 2026

Copy link
Copy Markdown
Member

#️⃣연관된 이슈

close #359

📝작업 내용

작업한 내용을 작성해주세요.


요약

플랫폼 운영자(BACKOFFICE) 역할 추가
전용 로그인 추가
/backoffice/** API 추가
백오피스 전용 감사 로그를 수집하기 위해 AOP 패턴 작성
기존 API에 @PreAuthorize RBAC를 일괄 적용하여 권한 분리 명확히함


A. 빌드 · 테스트 설정

파일 변경 설명
build.gradle 수정 spring-boot-starter-aop 추가 → @PreAuthorize + @BackofficeAudited Aspect 동작
application-test.yml 수정 테스트용 JWT secret, backoffice.bootstrap.enabled=false

B. 역할 · 엔티티 (데이터 모델)

파일 변경 설명
UserRole.java 수정 BACKOFFICE enum 추가
Member.java 수정 backofficeProfile 1:1 연관 추가
BackofficeUser.java 신규 백오피스 운영자 프로필 (name)
BackofficeUserRepository.java 신규 프로필 CRUD, bootstrap 0건 체크
BackofficeAuditLog.java 신규 감사 로그 테이블 엔티티
BackofficeAuditStatus.java 신규 SUCCESS / FAILURE

C. 백오피스 전용 인증

파일 변경 설명
BackofficeAuthController.java 신규 POST /auth/backoffice/login, /auth/backoffice/tokens/refresh
BackofficeAuthService.java 신규 인증 서비스 인터페이스
BackofficeAuthServiceImpl.java 신규 로그인: role=BACKOFFICE만 허용, aud=backoffice JWT 발급 / refresh 시 aud 검증
BackofficeLoginResponseDTO.java 신규 백오피스 로그인 응답 (tokens + basicInfo)
UserBasicInfoDTO.java 수정 BACKOFFICE case — 이름만 매핑
LoginServiceImpl.java 수정 commons/login·app refresh에서 BACKOFFICE 차단, 전용 로그인 유도
CommonAuthAdapter.java 수정 registerCredentialsmember.setCommonAuth() (bootstrap NPE 수정)
JwtUtil.java 수정 AUD_APP / AUD_BACKOFFICE, issueBackofficeTokens, assertAudience, refresh aud 유지
JwtAuthFilter.java 수정 URI별 audience 검증, backoffice login/refresh whitelist, CustomAuthException 재전파

흐름: 앱 JWT(aud=app) ↔ 백오피스 JWT(aud=backoffice) 상호 사용 불가.


D. Bootstrap · 운영자 관리

파일 변경 설명
BackofficeBootstrapInitializer.java 신규 backoffice.bootstrap.enabled=true + DB 0명일 때 @Value로 최초 운영자 1명 생성
BackofficeOperatorController.java 신규 POST/GET /backoffice/operators
BackofficeOperatorService.java 신규 create / list
BackofficeOperatorServiceImpl.java 신규 Member+CommonAuth+BackofficeUser 생성, 이메일 중복 검사
BackofficeOperatorCreateRequestDTO.java 신규 email, password, name
BackofficeOperatorResponseDTO.java 신규 memberId, email, name, status

E. 백오피스 운영 API (기존 API 이전)

파일 변경 설명
BackofficeStudentController.java 신규 POST /backoffice/students/sync (구 /students/sync/all 이전)
BackofficeInquiryController.java 신규 PATCH /backoffice/inquiries/{id}/answer (구 inquiry answer 이전)

둘 다 @PreAuthorize("hasRole('BACKOFFICE')") + mutating API에 @BackofficeAudited.


F. 감사 로그 (AOP)

파일 변경 설명
BackofficeAudited.java 신규 action, targetId(SpEL) 마커 어노테이션
BackofficeAuditAspect.java 신규 annotated 메서드 Around → HTTP/실행자/성공·실패 DB 저장
BackofficeAuditLogRepository.java 신규 JPA
BackofficeAuditLogService.java 신규 REQUIRES_NEW로 API rollback과 분리 저장

새 mutating API 추가 시: @BackofficeAudited(action = "...")만 붙이면 됨.


G. 전역 Security · RBAC 인프라

파일 변경 설명
MethodSecurityConfig.java 신규 @EnableMethodSecurity
SecurityConfig.java 수정 URL RBAC: /backoffice/**→BACKOFFICE, /admin/**→ADMIN, /partner/**→PARTNER; backoffice login permitAll; EntryPoint/AccessDeniedHandler 등록
RestAuthenticationEntryPoint.java 신규 미인증 → BaseResponse 401
RestAccessDeniedHandler.java 신규 권한 없음 → BaseResponse 403
SecurityErrorResponseWriter.java 신규 위 handler 공통 JSON 작성 util
GlobalExceptionAdvice.java 수정 AccessDeniedException → 403 BaseResponse
ErrorStatus.java 수정 NO_BACKOFFICE_TYPE, JWT_AUDIENCE_MISMATCH, BACKOFFICE_USE_DEDICATED_LOGIN, LAST_BACKOFFICE_OPERATOR

H. 기존 컨트롤러 — @PreAuthorize 적용

역할별 URL 접근 + 메서드 단위 이중 방어. 비즈니스 로직 변경 없음, 권한만 추가.

파일 적용 내용
AdminController.java @PreAuthorize("hasRole('ADMIN')")
StudentAdminController.java @PreAuthorize("hasRole('ADMIN')")
PartnerController.java @PreAuthorize("hasRole('PARTNER')")
StudentController.java @PreAuthorize("hasRole('STUDENT')") (+ sync endpoint 제거)
InquiryController.java @PreAuthorize("hasRole('STUDENTS')")
SuggestionController.java 클래스 STUDENT|ADMIN, 메서드별 분기
StoreController.java 클래스 STUDENT|ADMIN|BACKOFFICE, papers는 STUDENT, ranking은 PARTNER
MapController.java @PreAuthorize("hasAnyRole('STUDENT','ADMIN','PARTNER')")
PartnershipController.java 클래스 + 메서드별 ADMIN/PARTNER/STUDENT
MemberController.java STUDENT|ADMIN|PARTNER
NotificationController.java STUDENT|ADMIN|PARTNER
ChatController.java ADMIN|PARTNER
ReviewController.java 클래스 공통 + 메서드별 STUDENT/PARTNER
ReportController.java STUDENT|ADMIN|PARTNER
DeviceTokenController.java STUDENT|ADMIN|PARTNER
CertificationController.java @PreAuthorize("hasRole('STUDENT')")
GroupCertificationController.java @PreAuthorize("hasRole('STUDENT')")
AppReviewController.java @PreAuthorize("hasRole('STUDENT')")
TemporaryQrController.java @PreAuthorize("hasRole('STUDENT')")
RedirectController.java @PreAuthorize("hasRole('STUDENT')")

I. Partnership ownership (보안 구멍 수정)

파일 변경 설명
PartnershipService.java 수정 ownership 검증 메서드 시그니처
PartnershipServiceImpl.java 수정 assertPaperAccess() — ADMIN/PARTNER가 본인 paper만 get/update/delete

역할만 맞고 남의 리소스 접근하던 케이스 차단.


J. BACKOFFICE 추가 부수 수정

파일 변경 설명
NotificationCommandServiceImpl.java 수정 switch(role)BACKOFFICE → 알림 타입 없음
NotificationQueryServiceImpl.java 수정 동일

UserRole exhaustive switch 컴파일 대응.


K. 테스트

파일 변경 설명
BackofficeSecurityIntegrationTest.java 신규 BACKOFFICE 토큰 sync OK / app 토큰 audience 거부 / audit insert
BackofficeAuditAspectTest.java 신규 Aspect SUCCESS·FAILURE 로그 단위 테스트

기능별 파일 묶음 (역방향)

[1] BACKOFFICE 역할/계정
  UserRole, Member, BackofficeUser, BackofficeUserRepository

[2] 백오피스 로그인
  BackofficeAuthController, BackofficeAuthService*, BackofficeLoginResponseDTO
  JwtUtil, JwtAuthFilter, LoginServiceImpl, CommonAuthAdapter, UserBasicInfoDTO

[3] 운영자 bootstrap/CRUD
  BackofficeBootstrapInitializer, BackofficeOperator*, DTO 2개

[4] 운영 API 이전
  BackofficeStudentController, BackofficeInquiryController

[5] 감사 로그
  BackofficeAudited, BackofficeAuditAspect, BackofficeAuditLog*, BackofficeAuditLogService

[6] 전역 RBAC
  build.gradle, MethodSecurityConfig, SecurityConfig
  RestAuthenticationEntryPoint, RestAccessDeniedHandler, SecurityErrorResponseWriter
  GlobalExceptionAdvice, ErrorStatus

[7] 기존 API 권한
  Admin*, Partner*, Student*, Inquiry*, Suggestion*, Store*, Map*, Partnership*
  Member*, Notification*, Chat*, Review*, Report*, DeviceToken*
  Certification*, GroupCertification*, AppReview*, Qr*, Redirect*

[8] Partnership ownership
  PartnershipService*

[9] Notification switch
  NotificationCommand/QueryServiceImpl

[10] 테스트
  BackofficeSecurityIntegrationTest, BackofficeAuditAspectTest, application-test.yml

기타 변경사항

Before After
POST /students/sync/all POST /backoffice/students/sync (BACKOFFICE JWT)
PATCH /inquiries/{id}/answer (앱) PATCH /backoffice/inquiries/{id}/answer
commons/login으로 모든 role BACKOFFICE는 /auth/backoffice/login only
URL RBAC 거의 없음 /backoffice, /admin, /partner prefix RBAC
permitAll inquiry answer 제거

🔎코드 설명(스크린샷(선택))

코드에 대한 설명을 작성해주세요.

💬고민사항 및 리뷰 요구사항 (Optional)

고민사항 및 의견 받고 싶은 부분 있으면 적어두기

비고 (Optional)

참고했던 링크 등 참고 사항을 적어주세요. 코드 리뷰하는 사람이 참고해야 하는 내용을 자유로운 형식으로 적을 수 있습니다.

@2ghrms 2ghrms self-assigned this Jun 22, 2026
@2ghrms 2ghrms added the ✨ feature New feature or request label Jun 22, 2026
@2ghrms 2ghrms merged commit b276867 into develop Jun 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant