From 56b9b511c1bf1a951eac2f18d7ca62982038c26e Mon Sep 17 00:00:00 2001 From: devmrko Date: Wed, 22 Jul 2026 13:18:26 +0900 Subject: [PATCH] fix(backoffice): retain admin as control plane login --- docs/design/smilegate-tool-users/README.md | 6 +- .../vpdbackoffice/config/SecurityConfig.java | 59 ++++++------------- 2 files changed, 21 insertions(+), 44 deletions(-) diff --git a/docs/design/smilegate-tool-users/README.md b/docs/design/smilegate-tool-users/README.md index 01b1181..612dd39 100644 --- a/docs/design/smilegate-tool-users/README.md +++ b/docs/design/smilegate-tool-users/README.md @@ -6,7 +6,7 @@ ## 목표 -ADB의 `ADMIN.SG_TOOL_USER`를 백오피스 로그인 원본으로 사용한다. 가상 `sg-teamlead`와 `sg-member`를 만들고, 팀장만 변경 권한을 가진다. +백오피스의 `admin` 계정은 환경설정으로 유지한다. ADB의 `ADMIN.SG_TOOL_USER`에는 백오피스에서 관리할 가상 도구 사용자 `sg-teamlead`와 `sg-member`를 보관한다. ## 데이터 모델 @@ -20,8 +20,8 @@ ADB의 `ADMIN.SG_TOOL_USER`를 백오피스 로그인 원본으로 사용한다. ## 권한 매핑 -- `TEAM_LEAD` → `ROLE_ADMIN`: 설정 변경 가능 -- `TEAM_MEMBER` → `ROLE_VIEWER`: 조회만 가능 +- `TEAM_LEAD`: 팀장용 관리 대상 데이터 +- `TEAM_MEMBER`: 팀원용 관리 대상 데이터 ## 검증 기준 diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/config/SecurityConfig.java b/src/main/java/com/cloudhandson/vpdbackoffice/config/SecurityConfig.java index a131aa8..1fa6707 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/config/SecurityConfig.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/config/SecurityConfig.java @@ -1,6 +1,5 @@ package com.cloudhandson.vpdbackoffice.config; -import org.springframework.beans.factory.ObjectProvider; import java.util.ArrayList; import java.util.List; import org.springframework.context.annotation.Bean; @@ -10,12 +9,10 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.jdbc.core.JdbcTemplate; @Configuration public class SecurityConfig { @@ -78,48 +75,28 @@ public class SecurityConfig { @Bean UserDetailsService userDetailsService( - ObjectProvider jdbcTemplateProvider, BackofficeProperties properties, PasswordEncoder passwordEncoder ) { - JdbcTemplate jdbcTemplate = jdbcTemplateProvider.getIfAvailable(); - if (jdbcTemplate == null) { - String encodedPassword = properties.security().adminPasswordHash() == null - || properties.security().adminPasswordHash().isBlank() - ? passwordEncoder.encode(properties.security().adminPassword()) - : properties.security().adminPasswordHash(); - List users = new ArrayList<>(); - users.add(User.withUsername(properties.security().adminUser()) - .password(encodedPassword) - .roles("ADMIN") - .build()); - if (properties.security().guestConfigured()) { - String encodedGuestPassword = properties.security().guestPasswordHash() == null - || properties.security().guestPasswordHash().isBlank() - ? passwordEncoder.encode(properties.security().guestPassword()) - : properties.security().guestPasswordHash(); - users.add(User.withUsername(properties.security().guestUser()) - .password(encodedGuestPassword) - .roles("VIEWER") - .build()); - } - return new InMemoryUserDetailsManager(users); + var security = properties.security(); + String encodedPassword = security.adminPasswordHash() == null || security.adminPasswordHash().isBlank() + ? passwordEncoder.encode(security.adminPassword()) + : security.adminPasswordHash(); + List users = new ArrayList<>(); + users.add(User.withUsername(security.adminUser()) + .password(encodedPassword) + .roles("ADMIN") + .build()); + if (security.guestConfigured()) { + String encodedGuestPassword = security.guestPasswordHash() == null || security.guestPasswordHash().isBlank() + ? passwordEncoder.encode(security.guestPassword()) + : security.guestPasswordHash(); + users.add(User.withUsername(security.guestUser()) + .password(encodedGuestPassword) + .roles("VIEWER") + .build()); } - return username -> jdbcTemplate.query( - """ - select user_id, password_hash, role_code - from sg_tool_user - where user_id = ? - and enabled_yn = 'Y' - """, - (resultSet, rowNum) -> User.withUsername(resultSet.getString("user_id")) - .password(resultSet.getString("password_hash")) - .roles("TEAM_LEAD".equals(resultSet.getString("role_code")) ? "ADMIN" : "VIEWER") - .build(), - username - ).stream().findFirst().orElseThrow( - () -> new UsernameNotFoundException("Unknown or disabled tool user") - ); + return new InMemoryUserDetailsManager(users); } @Bean