Skip to content

20260202 #207 개발자용 관리자 페이지 구현#223

Merged
discipline24 merged 8 commits intomainfrom
20260202-#207-개발자용-관리자-페이지-구현
Feb 10, 2026

Hidden character warning

The head ref may contain hidden characters: "20260202-#207-\uac1c\ubc1c\uc790\uc6a9-\uad00\ub9ac\uc790-\ud398\uc774\uc9c0-\uad6c\ud604"
Merged

20260202 #207 개발자용 관리자 페이지 구현#223
discipline24 merged 8 commits intomainfrom
20260202-#207-개발자용-관리자-페이지-구현

Conversation

@nayoung04
Copy link
Contributor

@nayoung04 nayoung04 commented Feb 9, 2026

#207

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 관리자 인터페이스에 독립적인 로그인 시스템 추가
    • 애플리케이션 모니터링 엔드포인트(헬스, 메트릭, 로그 등) 활성화 및 관리자 콘텍스트 구성
    • 애플리케이션 로그를 파일에 저장하는 기능 추가
  • 보안

    • 관리자 및 모니터링 경로에 대한 별도 보안 필터 체인 적용
    • 일부 관리자·모니터링 경로가 JWT 인증 필터를 우회하도록 조정, 기존 허용 목록은 유지 및 일부 액추에이터 와일드카드 제한됨

@coderabbitai
Copy link

coderabbitai bot commented Feb 9, 2026

Warning

Rate limit exceeded

@nayoung04 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 11 minutes and 55 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

관리자 UI(/admin)와 액추에이터(/actuator) 경로를 메인 JWT 보안 체인에서 제외하고, 관리자 전용 SecurityFilterChain을 추가해 인메모리 관리자 사용자·폼 로그인·기본 인증 등을 구성하며 관련 애플리케이션 설정을 추가했습니다.

Changes

Cohort / File(s) Summary
JWT 필터 및 메인 보안 체인
backend/src/main/java/org/sejongisc/backend/common/auth/filter/JwtAuthenticationFilter.java, backend/src/main/java/org/sejongisc/backend/common/config/security/SecurityConfig.java
/admin, /actuator 경로를 JwtAuthenticationFilter에서 조기 제외하고 SecurityFilterChain에 securityMatcher를 추가해 해당 경로들이 메인 체인을 우회하도록 수정했습니다.
관리자 전용 보안 구성
backend/src/main/java/org/sejongisc/backend/common/config/security/AdminSecurityConfig.java
관리자 UI 전용 SecurityFilterChain을 새로 추가(인메모리 관리자 사용자, DaoAuthenticationProvider, PasswordEncoder, 폼 로그인 및 HTTP Basic, 정적 자원 허용, 인스턴스 등록 CSRF 예외 등).
화이트리스트 상수 변경
backend/src/main/java/org/sejongisc/backend/common/config/security/SecurityConstants.java
WHITELIST_URLS에서 "/actuator/**" 항목을 제거하여 액추에이터 경로에 대한 허용 범위를 축소했습니다.
애플리케이션 설정 (dev/prod)
backend/src/main/resources/application.yml, backend/src/main/resources/application-prod.yml
부트 어드민 컨텍스트(/admin), 관리 엔드포인트(관리자/액추에이터) 설정, 프로덕션용 admin 사용자 및 부트 어드민 메타데이터·인스턴스 정보, 로깅 파일 경로 등을 추가/수정했습니다.

Sequence Diagram(s)

sequenceDiagram
  participant Client as Client
  participant MainFilter as JwtAuthenticationFilter
  participant MainSecurity as Main SecurityFilterChain
  participant AdminSecurity as Admin SecurityFilterChain
  participant AuthProv as DaoAuthenticationProvider
  participant UserSvc as UserDetailsService

  Client->>MainFilter: 요청 (경로 검사)
  alt 요청이 /admin 또는 /actuator*
    MainFilter-->>Client: 필터 우회 -> 전달
    Client->>AdminSecurity: /admin 요청 처리
    AdminSecurity->>AuthProv: 인증 시도 (폼 또는 basic)
    AuthProv->>UserSvc: 사용자 조회
    UserSvc-->>AuthProv: 사용자정보
    AuthProv-->>AdminSecurity: 인증 토큰 발급
    AdminSecurity-->>Client: 응답 (인증/리다이렉트)
  else 기타 요청
    MainFilter->>MainSecurity: JWT 검증 흐름 (토큰 검사)
    MainSecurity-->>Client: 응답
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • discipline24

Poem

🐰 새 길 나눠 관리하네,
액추에이터는 따로 두고,
필터는 건너, 문은 따로 열어,
폼 로그인에 당근 한 조각—
홉! 안전한 점프를 축하해! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 개발자용 관리자 페이지 구현이라는 주요 변경사항을 정확하게 설명하고 있으며, 제공된 코드 변경사항(AdminSecurityConfig 추가, JWT 필터 설정, 보안 구성)과 일치합니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 20260202-#207-개발자용-관리자-페이지-구현

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@backend/build.gradle`:
- Line 70: The build file contains a duplicate dependency declaration for
org.springframework.boot:spring-boot-starter-security; remove the redundant
implementation 'org.springframework.boot:spring-boot-starter-security' entry
(the one shown in the diff) so only the single existing declaration remains (the
original declaration near the top), preventing confusion while keeping the
dependency.

In
`@backend/src/main/java/org/sejongisc/backend/common/config/security/AdminSecurityConfig.java`:
- Around line 37-93: The adminSecurityFilterChain currently configures formLogin
but omits logout handling; update adminSecurityFilterChain (HttpSecurity) to add
a logout configuration tied to adminContextPath (e.g., use
logout.logoutUrl(adminContextPath + "/logout") with
logoutSuccessUrl(adminContextPath + "/login?logout"),
invalidateHttpSession(true), clearAuthentication(true) and permitAll()) and
ensure the logout URL is allowed in the requestMatchers (or included in the
existing permitAll list) so admins can terminate sessions cleanly.

In `@backend/src/main/resources/application.yml`:
- Around line 23-34: Change the actuator health/details exposure to avoid
leaking internal secrets: update the
management.health.endpoint.health.show-details setting from "always" to
"when-authorized" and remove "heapdump" from the
management.endpoints.web.exposure.include list so JVM heap dumps are not
publicly exposed; locate the keys management.endpoint.health.show-details (or
management.health.endpoint.health.show-details) and
management.endpoints.web.exposure.include in the YAML and apply these two
changes so /actuator/health requires authorization for details and heapdump is
not included in the exposed endpoints.
🧹 Nitpick comments (2)
backend/src/main/java/org/sejongisc/backend/common/auth/filter/JwtAuthenticationFilter.java (1)

77-81: 방어적 코드로는 괜찮으나, SecurityConfigsecurityMatcher와 중복됩니다.

SecurityConfig.securityFilterChainsecurityMatcher가 이미 /admin, /actuator 경로를 메인 필터 체인에서 제외하므로, 이 필터의 shouldNotFilter까지 도달하지 않습니다. 방어적 중복이라면 주석으로 의도를 남겨두면 좋겠습니다.

backend/src/main/java/org/sejongisc/backend/common/config/security/SecurityConfig.java (1)

67-72: 람다 기반 securityMatcher는 디버깅과 Spring Security 내부 최적화에 불리합니다.

현재 람다를 사용하면 toString()이 의미 없는 값이 되어 디버그 로그에서 어떤 체인이 매칭되었는지 파악하기 어렵습니다. NegatedRequestMatcher 또는 커스텀 RequestMatcher 구현을 사용하면 가독성과 디버깅이 개선됩니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In
`@backend/src/main/java/org/sejongisc/backend/common/config/security/AdminSecurityConfig.java`:
- Line 79: In AdminSecurityConfig update the request matcher rules so the health
endpoint is public: replace the current .requestMatchers("/actuator/health",
"/actuator/info").hasRole("ADMIN") usage with two rules — allow
.requestMatchers("/actuator/health").permitAll() and keep sensitive endpoints
restricted (e.g. .requestMatchers("/actuator/info").hasRole("ADMIN") or other
admin-only actuator paths) so health checks from load balancers/K8s remain
unauthenticated while sensitive actuator endpoints still require ADMIN; modify
the security configuration where requestMatchers is used to reflect this
separation.
- Around line 75-76: The instance-registration endpoints are currently exposed
with .requestMatchers(adminContextPath + "/instances", adminContextPath +
"/instances/**").permitAll() (and CSRF disabled), which allows unauthenticated
registrations; change this to require HTTP Basic auth by replacing permitAll()
with an authentication requirement (e.g., .authenticated() or
.hasRole("SOME_ADMIN_ROLE")) for those requestMatchers and enable/configure
httpBasic() for the admin context, and ensure CSRF settings still allow the
intended client flow (or restrict CSRF disabling to only the necessary paths) so
registrations require credentials defined in application-prod.yml; update
references in AdminSecurityConfig to use adminContextPath + "/instances"
matchers, httpBasic(), and appropriate CSRF handling.
🧹 Nitpick comments (1)
backend/src/main/java/org/sejongisc/backend/common/config/security/AdminSecurityConfig.java (1)

40-44: UserDetails 생성을 별도의 @Bean으로 분리하는 것을 고려해 주세요.

현재 adminSecurityFilterChain 내부에서 InMemoryUserDetailsManagerDaoAuthenticationProvider를 직접 생성하고 있습니다. 이는 동작에 문제는 없지만, 테스트 용이성과 관심사 분리를 위해 별도 빈으로 추출하면 더 깔끔합니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@backend/src/main/java/org/sejongisc/backend/common/config/security/AdminSecurityConfig.java`:
- Around line 52-80: AdminSecurityConfig currently only matches adminContextPath
+ "/**" so /actuator/** bypasses all security; update the securityMatcher call
in AdminSecurityConfig to include "/actuator/**" as well (e.g.,
securityMatcher(adminContextPath + "/**", "/actuator/**")) and then keep or
adjust the authorizeHttpRequests block: retain the
requestMatchers("/actuator/health", "/actuator/info").permitAll() so health/info
remain public and let .anyRequest().authenticated() apply to other actuator
endpoints; verify the change in the securityMatcher invocation and the
authorizeHttpRequests() block (requestMatchers for actuator) to ensure actuator
endpoints are processed by this filter chain.

Copy link
Contributor

@discipline24 discipline24 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다~ 메인 풀을 안받아서 SecurityUrls 클래스가 없을수도 있는데, comment resolve시 참고해주세요~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants