diff --git a/build.gradle b/build.gradle
index 899d45bcc..50af1e314 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,8 +1,8 @@
plugins {
- id 'org.springframework.boot' version '2.7.18'
- id 'io.spring.dependency-management' version '1.0.15.RELEASE'
+ id 'org.springframework.boot' version '3.3.5'
+ id 'io.spring.dependency-management' version '1.1.6'
id 'java-library'
- id 'com.diffplug.spotless' version '6.13.0'
+ id 'com.diffplug.spotless' version '6.25.0'
}
spotless {
@@ -20,7 +20,7 @@ spotless {
//임포트 순서 정리
importOrder(
"java",
- "javax",
+ "jakarta",
"lombok",
"org.springframework",
"",
@@ -64,26 +64,33 @@ subprojects {
}
}
+ testing {
+ suites {
+ test {
+ useJUnitJupiter()
+ }
+ }
+ }
+
dependencies {
annotationProcessor(
'org.projectlombok:lombok',
'org.springframework.boot:spring-boot-configuration-processor',
'jakarta.persistence:jakarta.persistence-api',
'jakarta.annotation:jakarta.annotation-api',
- "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa"
+ 'com.querydsl:querydsl-apt:5.0.0:jakarta'
)
implementation (
'org.springframework.boot:spring-boot-starter-web',
'org.springframework.boot:spring-boot-starter-validation',
- 'org.springdoc:springdoc-openapi-ui:1.7.0',
+ 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0',
'com.google.code.findbugs:jsr305:3.0.2',
- 'io.awspring.cloud:spring-cloud-starter-aws:2.4.4',
// cloud config
- 'org.springframework.cloud:spring-cloud-starter-config:3.1.8',
+ 'org.springframework.cloud:spring-cloud-starter-config:4.1.4',
'org.springframework.boot:spring-boot-starter-actuator',
- 'org.springframework.cloud:spring-cloud-starter-bootstrap:3.1.8',
+ 'org.springframework.cloud:spring-cloud-starter-bootstrap:4.1.4',
// mail
'org.springframework.boot:spring-boot-starter-mail',
@@ -104,10 +111,6 @@ subprojects {
)
}
- test {
- useJUnitPlatform()
- }
-
}
project(':module-jpa') {
@@ -117,8 +120,8 @@ project(':module-jpa') {
dependencies {
api (
'org.springframework.boot:spring-boot-starter-data-jpa',
- 'com.querydsl:querydsl-jpa', // query dsl
- 'com.jcraft:jsch:0.1.55', // 로컬 개발용 db ssh tunneling, https://mavenlibs.com/maven/dependency/com.jcraft/jsch
+ 'com.querydsl:querydsl-jpa:5.0.0:jakarta',
+ 'com.jcraft:jsch:0.1.55',
// 'org.mariadb.jdbc:mariadb-java-client',
'com.mysql:mysql-connector-j',
'com.h2database:h2'
@@ -133,18 +136,18 @@ project(':module-auth') {
dependencies {
api project(':module-jpa')
// jwt
- api 'io.jsonwebtoken:jjwt-api:0.11.2'
- runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.2',
+ api 'io.jsonwebtoken:jjwt-api:0.11.5'
+ runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5',
// Uncomment the next line if you want to use RSASSA-PSS (PS256, PS384, PS512) algorithms:
//'org.bouncycastle:bcprov-jdk15on:1.60',
- 'io.jsonwebtoken:jjwt-jackson:0.11.2' // or 'io.jsonwebtoken:jjwt-gson:0.11.2' for gson
+ 'io.jsonwebtoken:jjwt-jackson:0.11.5'
// security
api 'org.springframework.boot:spring-boot-starter-security'
api 'org.springframework.boot:spring-boot-starter-oauth2-client'
- api 'javax.xml.bind:jaxb-api'
+ api 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.2'
testImplementation 'org.springframework.security:spring-security-test'
- testImplementation 'org.mockito:mockito-inline:2.13.0'
+ testImplementation 'org.mockito:mockito-inline:5.2.0'
}
}
@@ -155,9 +158,10 @@ project(':module-fileStorage') {
dependencies {
api project(':module-jpa')
- api 'javax.xml.bind:jaxb-api'
+ api 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.2'
+ implementation 'com.amazonaws:aws-java-sdk-s3:1.12.188'
testImplementation 'org.springframework.security:spring-security-test'
- testImplementation 'org.mockito:mockito-inline:2.13.0'
+ testImplementation 'org.mockito:mockito-inline:5.2.0'
}
}
@@ -167,6 +171,7 @@ project(':resource-server') {
api project(':module-auth')
api project(':module-fileStorage')
api 'org.springframework.boot:spring-boot-starter-security'
+ implementation 'com.amazonaws:aws-java-sdk-s3:1.12.188'
testImplementation 'org.springframework.security:spring-security-test'
}
@@ -174,7 +179,7 @@ project(':resource-server') {
delete file('src/main/generated')
}
- task cleanGeneratedDir(type: Delete) {
+ tasks.register('cleanGeneratedDir', Delete) {
delete file('src/main/generated')
}
}
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 84d1f85fd..48c0a02ca 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/config/AuthBeansConfig.java b/module-auth/src/main/java/com/inhabas/api/auth/config/AuthBeansConfig.java
index e5a6d4f39..a432e3db6 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/config/AuthBeansConfig.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/config/AuthBeansConfig.java
@@ -4,6 +4,7 @@
import lombok.RequiredArgsConstructor;
+import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -35,6 +36,11 @@ public class AuthBeansConfig {
private final AuthProperties authProperties;
private final RefreshTokenRepository refreshTokenRepository;
+ @Bean
+ public ApplicationRunner jwtSecretKeyStrengthChecker(JwtTokenUtil jwtTokenUtil) {
+ return args -> jwtTokenUtil.validateSecretKeyStrength();
+ }
+
@Bean
public HttpCookieOAuth2AuthorizationRequestRepository
httpCookieOAuth2AuthorizationRequestRepository() {
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/config/AuthSecurityConfig.java b/module-auth/src/main/java/com/inhabas/api/auth/config/AuthSecurityConfig.java
index 4cb67a490..7479742cc 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/config/AuthSecurityConfig.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/config/AuthSecurityConfig.java
@@ -2,13 +2,16 @@
import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
+import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsUtils;
import com.inhabas.api.auth.domain.oauth2.CustomOAuth2UserService;
@@ -18,9 +21,10 @@
@Order(0) // 인증 관련 security filter chain 은 우선순위가 가장 높아야 함.
@EnableWebSecurity
+@Configuration
@RequiredArgsConstructor
@Profile({"dev1", "dev2", "local", "prod1", "prod2"}) // 테스트에는 포함시키지 않음.
-public class AuthSecurityConfig extends WebSecurityConfigurerAdapter {
+public class AuthSecurityConfig {
private final CustomOAuth2UserService customOAuth2UserService;
private final OAuth2AuthorizedClientService authorizedClientService;
@@ -29,62 +33,40 @@ public class AuthSecurityConfig extends WebSecurityConfigurerAdapter {
private final HttpCookieOAuth2AuthorizationRequestRepository
httpCookieOAuth2AuthorizationRequestRepository;
- /**
- * 소셜 로그인 api
- *
- * 진행과정은 아래와 같다.
- *
- *
- * - 사용자가 소셜로그인 시작. (프론트에서 redirect_url 보내줘야함.)
- *
- OAuth2 인증 진행 -> 기존 회원인지 검사
- *
- * - 성공 -> OAuth2AuthenticationSuccessHandler
- *
- * - 프론트에서 보내준 redirect_url 검증 (-> 실패하면 failure handler 에서 처리)
- *
- jwt 토큰 발급 및 로그인 처리
- *
- 리다이렉트
- *
- * - 실패 -> OAuth2AuthenticationFailureHandler
- *
- *
- *
- * 회원가입이나, jwt 토큰 발급을 위한 url 로 함부로 접근할 수 없게 하기 위해 jwt 토근이 발급되기 이전까지는 OAuth2 인증 결과를 세션을 통해서 유지함.
- * 따라서 critical 한 url 에 대해서 OAuth2 인증이 완료된 세션에 한해서만 허용.
- */
- @Override
- protected void configure(HttpSecurity http) throws Exception {
+ @Bean
+ @Order(0)
+ public SecurityFilterChain authSecurityFilterChain(HttpSecurity http) throws Exception {
- http.requestMatchers()
- .antMatchers("/login/**")
- .and()
+ http
+ // /login/** 경로에만 이 보안 체인 적용
+ .securityMatcher("/login/**")
// 세션 생성 금지
- .sessionManagement()
- .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
- .and()
- .cors()
- .and()
- .authorizeRequests()
- .requestMatchers(CorsUtils::isPreFlightRequest)
- .permitAll()
- .anyRequest()
- .permitAll()
- .and()
- .csrf()
- .disable()
-
+ .sessionManagement(
+ session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+ .cors(cors -> {})
+ .csrf(AbstractHttpConfigurer::disable)
+ .authorizeHttpRequests(
+ authorize ->
+ authorize
+ .requestMatchers(request -> CorsUtils.isPreFlightRequest(request))
+ .permitAll()
+ .anyRequest()
+ .permitAll())
// Oauth 로그인 설정
- .oauth2Login()
- .authorizedClientService(authorizedClientService)
- .authorizationEndpoint()
- .baseUri("/login/oauth2/authorization")
- .authorizationRequestRepository(httpCookieOAuth2AuthorizationRequestRepository)
- .and()
+ .oauth2Login(
+ oauth2 ->
+ oauth2
+ .authorizedClientService(authorizedClientService)
+ .authorizationEndpoint(
+ authorization ->
+ authorization
+ .baseUri("/login/oauth2/authorization")
+ .authorizationRequestRepository(
+ httpCookieOAuth2AuthorizationRequestRepository))
+ .userInfoEndpoint(userInfo -> userInfo.userService(customOAuth2UserService))
+ .failureHandler(oauth2AuthenticationFailureHandler)
+ .successHandler(oauth2AuthenticationSuccessHandler));
- // 사용자 정보를 가져오는 엔드포인트에 대한 설정
- .userInfoEndpoint()
- .userService(customOAuth2UserService)
- .and()
- .failureHandler(oauth2AuthenticationFailureHandler)
- .successHandler(oauth2AuthenticationSuccessHandler);
+ return http.build();
}
}
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/config/TemplateConfig.java b/module-auth/src/main/java/com/inhabas/api/auth/config/TemplateConfig.java
index e238c1a02..6c64986d8 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/config/TemplateConfig.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/config/TemplateConfig.java
@@ -4,8 +4,8 @@
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.TemplateEngine;
-import org.thymeleaf.spring5.SpringTemplateEngine;
-import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
+import org.thymeleaf.spring6.SpringTemplateEngine;
+import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.templatemode.TemplateMode;
@Configuration
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtils.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtils.java
index 521c40957..de5eec814 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtils.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtils.java
@@ -1,26 +1,45 @@
package com.inhabas.api.auth.domain.oauth2.cookie;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.time.Duration;
import java.util.Base64;
-import java.util.Objects;
import java.util.Optional;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.http.ResponseCookie;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
-import org.springframework.util.SerializationUtils;
-
-import io.micrometer.core.instrument.util.StringUtils;
public interface CookieUtils {
+ enum SameSite {
+ LAX("Lax"),
+ STRICT("Strict"),
+ NONE("None");
+ private final String value;
+
+ SameSite(String v) {
+ this.value = v;
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+
/** request 에 담겨 있는 쿠키를 꺼낸다. */
static Optional resolveCookie(HttpServletRequest request, String cookieName) {
Cookie[] cookies = request.getCookies();
- if (cookies != null && cookies.length > 0) {
+ if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(cookieName)) {
return Optional.of(cookie);
@@ -31,38 +50,80 @@ static Optional resolveCookie(HttpServletRequest request, String cookieN
return Optional.empty();
}
- /** 쿠키를 지우는 작업은 없고, maxAge 를 0으로 설정해서 브라우저가 파기하도록 한다. */
+ /** 기본 삭제: SameSite=Lax, Secure=request.isSecure(), path="/" 로 설정하여 Max-Age=0 으로 파기. */
static void deleteCookie(
HttpServletRequest request, HttpServletResponse response, String cookieName) {
- Cookie[] cookies = request.getCookies();
- if (cookies != null && cookies.length > 0) {
- for (Cookie cookie : cookies) {
- if (cookie.getName().equals(cookieName)) {
- cookie.setValue("");
- cookie.setPath("/");
- cookie.setMaxAge(0);
- response.addCookie(cookie);
- break;
- }
- }
+ // 동일 이름 쿠키를 빈 값과 Max-Age=0 으로 덮어써서 삭제
+ deleteCookie(request, response, cookieName, SameSite.LAX, null);
+ }
+
+ /**
+ * 생성 시와 동일한 속성으로 삭제할 수 있도록 SameSite/Secure 를 제어하는 오버로드. secure=null 이면 request.isSecure() 사용.
+ * SameSite=None 이면 Secure=true 강제.
+ */
+ static void deleteCookie(
+ HttpServletRequest request,
+ HttpServletResponse response,
+ String cookieName,
+ SameSite sameSite,
+ Boolean secure) {
+
+ boolean secureFlag = secure != null ? secure : request.isSecure();
+ if (sameSite == SameSite.NONE && !secureFlag) {
+ // 브라우저 정책: SameSite=None 은 Secure 필요. 강제 상승.
+ secureFlag = true;
}
+
+ ResponseCookie rc =
+ ResponseCookie.from(cookieName, "")
+ .path("/")
+ .httpOnly(true)
+ .secure(secureFlag)
+ .maxAge(Duration.ZERO)
+ .sameSite(sameSite.toString())
+ .build();
+ response.addHeader("Set-Cookie", rc.toString());
+ }
+
+ /** 기본값: SameSite=Lax, Secure=request.isSecure() */
+ static void setCookie(
+ HttpServletRequest request,
+ HttpServletResponse response,
+ String cookieName,
+ String cookieContents,
+ int maxAge) {
+ setCookie(request, response, cookieName, cookieContents, maxAge, SameSite.LAX, null);
}
/**
- * @param response 응답에 쿠키를 적어서 보내줌
- * @param cookieName key
- * @param cookieContents value
- * @param maxAge 초 단위
+ * SameSite/Secure 를 제어할 수 있는 오버로드. secure=null 이면 request.isSecure() 사용. SameSite=None 이면
+ * Secure=true 강제.
*/
static void setCookie(
- HttpServletResponse response, String cookieName, String cookieContents, int maxAge) {
+ HttpServletRequest request,
+ HttpServletResponse response,
+ String cookieName,
+ String cookieContents,
+ int maxAge,
+ SameSite sameSite,
+ Boolean secure) {
+
+ boolean secureFlag = secure != null ? secure : request.isSecure();
+ if (sameSite == SameSite.NONE && !secureFlag) {
+ // 브라우저 정책: SameSite=None 은 Secure 필요. 강제 상승.
+ secureFlag = true;
+ }
- Cookie cookie = new Cookie(cookieName, cookieContents);
- cookie.setPath("/");
- cookie.setHttpOnly(true);
- cookie.setMaxAge(maxAge);
- response.addCookie(cookie);
+ ResponseCookie rc =
+ ResponseCookie.from(cookieName, cookieContents)
+ .path("/")
+ .httpOnly(true)
+ .secure(secureFlag)
+ .maxAge(Duration.ofSeconds(Math.max(0, maxAge)))
+ .sameSite(sameSite.toString())
+ .build();
+ response.addHeader("Set-Cookie", rc.toString());
}
/**
@@ -70,8 +131,14 @@ static void setCookie(
* @return 브라우저 쿠키에 담기 위해 OAuth2AuthorizationRequest 를 string 으로 변환.
*/
static String serialize(OAuth2AuthorizationRequest request) {
-
- return Base64.getUrlEncoder().encodeToString(SerializationUtils.serialize(request));
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+ oos.writeObject(request);
+ oos.flush();
+ return Base64.getUrlEncoder().encodeToString(bos.toByteArray());
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to serialize OAuth2AuthorizationRequest", e);
+ }
}
/**
@@ -81,13 +148,19 @@ static String serialize(OAuth2AuthorizationRequest request) {
*/
static T deserialize(Cookie cookie, Class clz) {
- if (isDeleted(cookie)) return null;
- else
- return clz.cast(
- SerializationUtils.deserialize(Base64.getUrlDecoder().decode(cookie.getValue())));
+ if (cookie == null || isBlank(cookie.getValue())) return null;
+ try {
+ byte[] data = Base64.getUrlDecoder().decode(cookie.getValue());
+ try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data))) {
+ Object obj = ois.readObject();
+ return clz.cast(obj);
+ }
+ } catch (IOException | ClassNotFoundException | IllegalArgumentException ex) {
+ return null;
+ }
}
- private static boolean isDeleted(Cookie cookie) {
- return StringUtils.isBlank(cookie.getValue()) || Objects.isNull(cookie.getValue());
+ private static boolean isBlank(String s) {
+ return s == null || s.trim().isEmpty();
}
}
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepository.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepository.java
index 9173941e4..172982f8b 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepository.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepository.java
@@ -1,7 +1,7 @@
package com.inhabas.api.auth.domain.oauth2.cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
@@ -35,28 +35,37 @@ public void saveAuthorizationRequest(
HttpServletRequest request,
HttpServletResponse response) {
if (authorizationRequest == null) {
- CookieUtils.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME);
- CookieUtils.deleteCookie(request, response, REDIRECT_URL_PARAM_COOKIE_NAME);
+ CookieUtils.deleteCookie(
+ request,
+ response,
+ OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME,
+ CookieUtils.SameSite.LAX,
+ null);
+ CookieUtils.deleteCookie(
+ request, response, REDIRECT_URL_PARAM_COOKIE_NAME, CookieUtils.SameSite.LAX, null);
return;
}
CookieUtils.setCookie(
+ request,
response,
OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME,
CookieUtils.serialize(authorizationRequest),
- cookieExpireSeconds);
+ cookieExpireSeconds,
+ CookieUtils.SameSite.LAX,
+ null);
String redirectUrlAfterLogin = request.getParameter(REDIRECT_URL_PARAM_COOKIE_NAME);
if (StringUtils.isNotBlank(redirectUrlAfterLogin)) {
CookieUtils.setCookie(
- response, REDIRECT_URL_PARAM_COOKIE_NAME, redirectUrlAfterLogin, cookieExpireSeconds);
+ request,
+ response,
+ REDIRECT_URL_PARAM_COOKIE_NAME,
+ redirectUrlAfterLogin,
+ cookieExpireSeconds,
+ CookieUtils.SameSite.LAX,
+ null);
}
}
- @Deprecated
- @Override
- public OAuth2AuthorizationRequest removeAuthorizationRequest(HttpServletRequest request) {
- return null;
- }
-
/**
* OAuth2AuthorizationRequest 를 쿠키에서 제거함.
*
@@ -68,14 +77,25 @@ public OAuth2AuthorizationRequest removeAuthorizationRequest(
// 쿠키 삭제하기 전에 쿠키 문자열을 객체로 변환
OAuth2AuthorizationRequest authorizationRequest = this.loadAuthorizationRequest(request);
- CookieUtils.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME);
+ CookieUtils.deleteCookie(
+ request,
+ response,
+ OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME,
+ CookieUtils.SameSite.LAX,
+ null);
return authorizationRequest;
}
/** redirect_url이 담긴 쿠키는 인증이 완전히 완료된 후에 제거되어야함. */
public void clearCookies(HttpServletRequest request, HttpServletResponse response) {
- CookieUtils.deleteCookie(request, response, OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME);
- CookieUtils.deleteCookie(request, response, REDIRECT_URL_PARAM_COOKIE_NAME);
+ CookieUtils.deleteCookie(
+ request,
+ response,
+ OAUTH2_AUTHORIZATION_REQUEST_COOKIE_NAME,
+ CookieUtils.SameSite.LAX,
+ null);
+ CookieUtils.deleteCookie(
+ request, response, REDIRECT_URL_PARAM_COOKIE_NAME, CookieUtils.SameSite.LAX, null);
}
}
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandler.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandler.java
index 78a374ad0..c249ae698 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandler.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandler.java
@@ -4,8 +4,8 @@
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandler.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandler.java
index 8cd4277df..879c29010 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandler.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandler.java
@@ -4,9 +4,9 @@
import java.io.IOException;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/MajorInfo.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/MajorInfo.java
index fe539ed29..59217e65d 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/MajorInfo.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/MajorInfo.java
@@ -1,6 +1,6 @@
package com.inhabas.api.auth.domain.oauth2.majorInfo.domain;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/College.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/College.java
index 33aff6517..4eba43d12 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/College.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/College.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import com.inhabas.api.auth.domain.error.businessException.InvalidInputException;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/Major.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/Major.java
index 8bc1428f4..4c9f25298 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/Major.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/domain/valueObject/Major.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import com.inhabas.api.auth.domain.error.businessException.InvalidInputException;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/dto/MajorInfoSaveDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/dto/MajorInfoSaveDto.java
index ae19f0939..7d92ba2e6 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/dto/MajorInfoSaveDto.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/majorInfo/dto/MajorInfoSaveDto.java
@@ -1,6 +1,6 @@
package com.inhabas.api.auth.domain.oauth2.majorInfo.dto;
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.NoArgsConstructor;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java
index 4c73b7ef6..164a92473 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/Member.java
@@ -4,7 +4,7 @@
import java.time.LocalDateTime;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
@@ -26,7 +26,7 @@
uniqueConstraints = {
@UniqueConstraint(
name = "UNIQUE_PROVIDER_UID",
- columnNames = {"provider", "uid"})
+ columnNames = {"provider", "UID"})
})
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/UpdateNameRequest.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/UpdateNameRequest.java
index 9bbb2a070..8d6b73921 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/UpdateNameRequest.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/entity/UpdateNameRequest.java
@@ -4,7 +4,7 @@
import java.time.LocalDateTime;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Email.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Email.java
index 732c7e054..6f0aaeb74 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Email.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Email.java
@@ -3,8 +3,8 @@
import java.util.Objects;
import java.util.regex.Pattern;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
import com.inhabas.api.auth.domain.error.businessException.InvalidInputException;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Generation.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Generation.java
index 339f99c65..d720f04f7 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Generation.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Generation.java
@@ -2,8 +2,8 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
import lombok.Getter;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Grade.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Grade.java
index a650a227f..fa2f54201 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Grade.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Grade.java
@@ -2,8 +2,8 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
import lombok.Getter;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/IbasInformation.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/IbasInformation.java
index 3a76f7e8d..3e50a99f8 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/IbasInformation.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/IbasInformation.java
@@ -3,7 +3,7 @@
import java.time.LocalDateTime;
import java.util.Objects;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Introduce.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Introduce.java
index 9cc85840f..2c3274d15 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Introduce.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Introduce.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import com.inhabas.api.auth.domain.error.businessException.InvalidInputException;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Name.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Name.java
index f5503b0c5..8f02f2a61 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Name.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Name.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import com.inhabas.api.auth.domain.error.businessException.InvalidInputException;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Phone.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Phone.java
index 266853ff1..89c90c375 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Phone.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/Phone.java
@@ -3,8 +3,8 @@
import java.util.Objects;
import java.util.regex.Pattern;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
import lombok.Getter;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/SchoolInformation.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/SchoolInformation.java
index 4baeabec1..addf3d12d 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/SchoolInformation.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/SchoolInformation.java
@@ -2,7 +2,7 @@
import java.util.Objects;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/StudentId.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/StudentId.java
index 3cdd5eb9c..b6dab2046 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/StudentId.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/domain/valueObject/StudentId.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ApprovedMemberManagementDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ApprovedMemberManagementDto.java
index 7ec5602e5..d52b88afb 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ApprovedMemberManagementDto.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ApprovedMemberManagementDto.java
@@ -1,9 +1,9 @@
package com.inhabas.api.auth.domain.oauth2.member.dto;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Pattern;
-import javax.validation.constraints.Positive;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Positive;
import lombok.AllArgsConstructor;
import lombok.Data;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ApprovedMemberSummaryDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ApprovedMemberSummaryDto.java
index eddb9a894..8fd9ce415 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ApprovedMemberSummaryDto.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ApprovedMemberSummaryDto.java
@@ -1,7 +1,7 @@
package com.inhabas.api.auth.domain.oauth2.member.dto;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Getter;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ContactDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ContactDto.java
index 9a502ee6c..d80a7d8b0 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ContactDto.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ContactDto.java
@@ -1,6 +1,6 @@
package com.inhabas.api.auth.domain.oauth2.member.dto;
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.NoArgsConstructor;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ExecutiveMemberDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ExecutiveMemberDto.java
index fad17c2a0..6eae631ec 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ExecutiveMemberDto.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ExecutiveMemberDto.java
@@ -1,8 +1,8 @@
package com.inhabas.api.auth.domain.oauth2.member.dto;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
import lombok.Builder;
import lombok.Getter;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/HallOfFameDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/HallOfFameDto.java
index e8c0c3116..658654e8b 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/HallOfFameDto.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/HallOfFameDto.java
@@ -1,10 +1,10 @@
package com.inhabas.api.auth.domain.oauth2.member.dto;
-import javax.validation.constraints.Email;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Pattern;
-import javax.validation.constraints.Positive;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Positive;
import lombok.Builder;
import lombok.Getter;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/HandleNameRequestDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/HandleNameRequestDto.java
index 393296f2c..9a8088973 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/HandleNameRequestDto.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/HandleNameRequestDto.java
@@ -1,7 +1,7 @@
package com.inhabas.api.auth.domain.oauth2.member.dto;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Getter;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/MyProfileDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/MyProfileDto.java
index 1b0a941e3..2ec223200 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/MyProfileDto.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/MyProfileDto.java
@@ -1,6 +1,6 @@
package com.inhabas.api.auth.domain.oauth2.member.dto;
-import javax.validation.constraints.*;
+import jakarta.validation.constraints.*;
import lombok.*;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/NotApprovedMemberManagementDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/NotApprovedMemberManagementDto.java
index a75d237c8..b2c3c6fe6 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/NotApprovedMemberManagementDto.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/NotApprovedMemberManagementDto.java
@@ -1,6 +1,6 @@
package com.inhabas.api.auth.domain.oauth2.member.dto;
-import javax.validation.constraints.*;
+import jakarta.validation.constraints.*;
import lombok.*;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileNameDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileNameDto.java
index a0cd73328..8878d29e8 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileNameDto.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/ProfileNameDto.java
@@ -1,6 +1,6 @@
package com.inhabas.api.auth.domain.oauth2.member.dto;
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
import lombok.*;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/UpdateNameRequestDto.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/UpdateNameRequestDto.java
index 1e75ed0b4..46f8d27a7 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/UpdateNameRequestDto.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/dto/UpdateNameRequestDto.java
@@ -2,8 +2,8 @@
import java.time.LocalDateTime;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Getter;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/DefaultRoleHierarchy.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/DefaultRoleHierarchy.java
index d0956a32c..a56e96c48 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/DefaultRoleHierarchy.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/member/security/DefaultRoleHierarchy.java
@@ -29,8 +29,6 @@ public class DefaultRoleHierarchy implements Hierarchical {
@Override
public RoleHierarchy getHierarchy() {
- RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
-
Map> roleHierarchyMap =
new HashMap<>() {
{
@@ -62,14 +60,12 @@ public RoleHierarchy getHierarchy() {
put(SECRETARY, Arrays.asList(BASIC, DEACTIVATED, NOT_APPROVED, ANONYMOUS));
put(BASIC, Arrays.asList(DEACTIVATED, NOT_APPROVED, ANONYMOUS));
put(DEACTIVATED, Arrays.asList(NOT_APPROVED, ANONYMOUS));
- put(NOT_APPROVED, Arrays.asList(ANONYMOUS));
- put(SIGNING_UP, Arrays.asList(ANONYMOUS));
+ put(NOT_APPROVED, Collections.singletonList(ANONYMOUS));
+ put(SIGNING_UP, Collections.singletonList(ANONYMOUS));
}
};
String roles = RoleHierarchyUtils.roleHierarchyFromMap(roleHierarchyMap);
- roleHierarchy.setHierarchy(roles);
-
- return roleHierarchy;
+ return RoleHierarchyImpl.fromHierarchy(roles);
}
}
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/entity/MemberSocialAccount.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/entity/MemberSocialAccount.java
index ea0209c9d..11d3b6b11 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/entity/MemberSocialAccount.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/entity/MemberSocialAccount.java
@@ -1,6 +1,6 @@
package com.inhabas.api.auth.domain.oauth2.socialAccount.domain.entity;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/valueObject/UID.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/valueObject/UID.java
index a6b19cc6b..24a663abf 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/valueObject/UID.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/oauth2/socialAccount/domain/valueObject/UID.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import com.inhabas.api.auth.domain.error.businessException.InvalidInputException;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/CustomRequestMatcher.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/CustomRequestMatcher.java
index 6f491bbe0..b407debc5 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/CustomRequestMatcher.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/CustomRequestMatcher.java
@@ -1,6 +1,6 @@
package com.inhabas.api.auth.domain.token;
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/JwtAccessDeniedHandler.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/JwtAccessDeniedHandler.java
index 85413c89a..40d9c72a5 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/JwtAccessDeniedHandler.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/JwtAccessDeniedHandler.java
@@ -5,9 +5,9 @@
import java.io.IOException;
import java.io.OutputStream;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenResolver.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenResolver.java
index bffb1d09f..55f083aee 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenResolver.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/TokenResolver.java
@@ -1,6 +1,6 @@
package com.inhabas.api.auth.domain.token;
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
public interface TokenResolver {
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenResolver.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenResolver.java
index e112f30fd..3f04af41c 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenResolver.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenResolver.java
@@ -1,6 +1,6 @@
package com.inhabas.api.auth.domain.token.jwtUtils;
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
import org.springframework.util.StringUtils;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenUtil.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenUtil.java
index 8fe1980b8..b3b55bcf4 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenUtil.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/JwtTokenUtil.java
@@ -3,8 +3,11 @@
import java.security.Key;
import java.util.Date;
import java.util.List;
+import java.util.UUID;
import java.util.stream.Collectors;
+import jakarta.annotation.PostConstruct;
+
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -28,6 +31,7 @@
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
+import io.jsonwebtoken.security.WeakKeyException;
// https://github.com/jwtk/jjwt
@Slf4j
@@ -40,35 +44,116 @@ public class JwtTokenUtil implements TokenUtil {
@Value("${jwt.secretKey}")
private String SECRET_KEY;
- private final Long ACCESS_TOKEN_VALID_MILLISECOND = 30 * 60 * 1000L; // 0.5 hour
- private static final Long REFRESH_TOKEN_VALID_MILLI_SECOND = 7 * 24 * 60 * 60 * 1000L; // 7 days
+ @Value("${jwt.issuer:inhabas.com}")
+ private String ISSUER;
+
+ @Value("${jwt.audience:inhabas-client}")
+ private String AUDIENCE;
+
+ private final Long ACCESS_TOKEN_VALID_MILLIS = 30 * 60 * 1000L; // 0.5 hour
+ private static final Long REFRESH_TOKEN_VALID_MILLIS = 7 * 24 * 60 * 60 * 1000L; // 7 days
private static final String AUTHORITY = "authorities";
private static final String MEMBER_ID = "memberId";
private static final String MEMBER_NAME = "memberName";
private static final String MEMBER_PICTURE = "memberPicture";
+ private static final int MIN_HS512_KEY_BYTES = 64; // 512 bits
+
+ // 캐시된 키와 파서
+ private volatile Key signingKey;
+ private volatile JwtParser jwtParser;
+
+ @PostConstruct
+ public void init() {
+ validateSecretKeyStrength();
+ }
+
+ /** HS512 용 시크릿 키 강도 검증 및 Key/Parser 캐싱. */
+ public void validateSecretKeyStrength() {
+ if (SECRET_KEY == null || SECRET_KEY.trim().isEmpty()) {
+ throw new IllegalStateException("jwt.secretKey is not configured or blank");
+ }
+
+ final byte[] decoded;
+ try {
+ decoded = Decoders.BASE64.decode(SECRET_KEY.trim());
+ } catch (IllegalArgumentException e) {
+ throw new IllegalStateException("jwt.secretKey must be Base64-encoded", e);
+ }
+
+ if (decoded.length < MIN_HS512_KEY_BYTES) {
+ throw new IllegalStateException(
+ "Weak jwt.secretKey for HS512: require >= 64 bytes after Base64 decoding, got "
+ + decoded.length
+ + " bytes");
+ }
+
+ try {
+ // 키/파서 캐시 생성 (WeakKeyException 등 조기 검출)
+ Key key = Keys.hmacShaKeyFor(decoded);
+ this.signingKey = key;
+ this.jwtParser =
+ Jwts.parserBuilder()
+ .setSigningKey(key)
+ .requireIssuer(ISSUER)
+ .requireAudience(AUDIENCE)
+ .build();
+ } catch (WeakKeyException e) {
+ throw new IllegalStateException("Weak jwt.secretKey: " + e.getMessage(), e);
+ }
+ }
+
+ private Key getSigningKey() {
+ Key key = this.signingKey;
+ if (key != null) {
+ return key;
+ }
+ // lazy-init (테스트 등 부팅 훅 없이 사용되는 경우 대비)
+ Key newKey = Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET_KEY));
+ this.signingKey = newKey;
+ return newKey;
+ }
+
+ private JwtParser getJwtParser() {
+ JwtParser parser = this.jwtParser;
+ if (parser != null) {
+ return parser;
+ }
+ // lazy-init
+ JwtParser newParser =
+ Jwts.parserBuilder()
+ .setSigningKey(getSigningKey())
+ .requireIssuer(ISSUER)
+ .requireAudience(AUDIENCE)
+ .build();
+ this.jwtParser = newParser;
+ return newParser;
+ }
@Override
public String createAccessToken(Authentication authentication) {
- return createToken(authentication, ACCESS_TOKEN_VALID_MILLISECOND);
+ return createToken(authentication, ACCESS_TOKEN_VALID_MILLIS);
}
@Override
public String createRefreshToken(Authentication authentication) {
- String token = this.createToken(authentication, REFRESH_TOKEN_VALID_MILLI_SECOND);
+ String token = this.createToken(authentication, REFRESH_TOKEN_VALID_MILLIS);
refreshTokenRepository.save(new RefreshToken(token));
return token;
}
@Override
public Long getExpiration() {
- return this.ACCESS_TOKEN_VALID_MILLISECOND / 1000;
+ // 초 단위로 통일
+ return this.ACCESS_TOKEN_VALID_MILLIS / 1000;
}
private String createToken(Authentication authentication, Long expiration) {
- assert authentication != null;
+ if (authentication == null) {
+ throw new IllegalArgumentException("authentication must not be null");
+ }
OAuth2UserInfo oAuth2UserInfo =
OAuth2UserInfoFactory.getOAuth2UserInfo((OAuth2AuthenticationToken) authentication);
@@ -83,10 +168,13 @@ private String createToken(Authentication authentication, Long expiration) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + expiration);
- final Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET_KEY));
+ final Key key = getSigningKey();
return Jwts.builder()
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
+ .setIssuer(ISSUER)
+ .setAudience(AUDIENCE)
+ .setId(UUID.randomUUID().toString())
.setSubject(uid)
.claim(MEMBER_ID, customOAuth2User.getMemberId())
.claim(MEMBER_NAME, customOAuth2User.getMemberName())
@@ -102,7 +190,7 @@ private String createToken(Authentication authentication, Long expiration) {
public void validate(String token) {
try {
- Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token);
+ getJwtParser().parseClaimsJws(token);
} catch (SecurityException ex) {
log.error("Invalid JWT signature");
throw new InvalidTokenException();
@@ -130,8 +218,11 @@ public JwtAuthenticationToken getAuthentication(String token) throws JwtExceptio
Claims claims = this.parseClaims(token);
- Long memberId = claims.get(MEMBER_ID, Long.class);
+ Number memberIdNumber = claims.get(MEMBER_ID, Number.class);
+ Long memberId = memberIdNumber == null ? null : memberIdNumber.longValue();
+
List> rawAuthorities = claims.get(AUTHORITY, List.class);
+ if (rawAuthorities == null) rawAuthorities = List.of();
List grantedAuthorities =
rawAuthorities.stream()
@@ -145,7 +236,7 @@ public JwtAuthenticationToken getAuthentication(String token) throws JwtExceptio
/* 토큰 body 에 넣어둔 사용자 정보를 가져옴
* validation 검사를 먼저 꼭 해야함! */
private Claims parseClaims(String token) throws JwtException {
- return Jwts.parserBuilder().setSigningKey(SECRET_KEY).build().parseClaimsJws(token).getBody();
+ return getJwtParser().parseClaimsJws(token).getBody();
}
@Override
@@ -162,14 +253,37 @@ public TokenDto reissueAccessTokenUsing(String refreshToken) throws InvalidToken
private TokenDto createAccessTokenOnly(Claims claims) {
Date now = new Date();
- final Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET_KEY));
+ final Key key = getSigningKey();
+
+ // 화이트리스트 기반으로 클레임 재구성: 필요한 필드만 복사
+ String subject = claims.getSubject();
+ Number memberIdNumber = claims.get(MEMBER_ID, Number.class);
+ Long memberId = memberIdNumber == null ? null : memberIdNumber.longValue();
+ String memberName = claims.get(MEMBER_NAME, String.class);
+ String memberPicture = claims.get(MEMBER_PICTURE, String.class);
+ List> rawAuthorities = claims.get(AUTHORITY, List.class);
+
+ List authorities =
+ rawAuthorities == null
+ ? List.of()
+ : rawAuthorities.stream()
+ .filter(v -> v instanceof String)
+ .map(v -> (String) v)
+ .collect(Collectors.toList());
String accessToken =
Jwts.builder()
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
- .setClaims(claims)
+ .setIssuer(ISSUER)
+ .setAudience(AUDIENCE)
+ .setId(UUID.randomUUID().toString())
+ .setSubject(subject)
+ .claim(MEMBER_ID, memberId)
+ .claim(MEMBER_NAME, memberName)
+ .claim(MEMBER_PICTURE, memberPicture)
+ .claim(AUTHORITY, authorities)
.setIssuedAt(now)
- .setExpiration(new Date(now.getTime() + ACCESS_TOKEN_VALID_MILLISECOND))
+ .setExpiration(new Date(now.getTime() + ACCESS_TOKEN_VALID_MILLIS))
.signWith(key, SignatureAlgorithm.HS512)
.compact();
@@ -177,7 +291,7 @@ private TokenDto createAccessTokenOnly(Claims claims) {
.grantType("Bearer")
.accessToken(accessToken)
.refreshToken("")
- .accessTokenExpireDate(ACCESS_TOKEN_VALID_MILLISECOND)
+ .accessTokenExpireDate(ACCESS_TOKEN_VALID_MILLIS / 1000) // 초 단위
.build();
}
}
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshToken.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshToken.java
index 81259f68e..be4da461d 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshToken.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/jwtUtils/refreshToken/RefreshToken.java
@@ -2,7 +2,7 @@
import java.time.LocalDateTime;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationEntryPoint.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationEntryPoint.java
index 72bf2b928..f0d186162 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationEntryPoint.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationEntryPoint.java
@@ -5,9 +5,9 @@
import java.io.IOException;
import java.io.OutputStream;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
diff --git a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationFilter.java b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationFilter.java
index dae574bb0..e1523de54 100644
--- a/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationFilter.java
+++ b/module-auth/src/main/java/com/inhabas/api/auth/domain/token/securityFilter/JwtAuthenticationFilter.java
@@ -6,10 +6,10 @@
import java.io.OutputStream;
import java.util.Collections;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@@ -23,6 +23,7 @@
import org.springframework.security.web.util.matcher.RequestMatcher;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.inhabas.api.auth.domain.error.ErrorCode;
import com.inhabas.api.auth.domain.error.ErrorResponse;
import com.inhabas.api.auth.domain.error.authException.CustomAuthException;
import com.inhabas.api.auth.domain.token.TokenResolver;
@@ -47,7 +48,7 @@ public JwtAuthenticationFilter(
@Override
public Authentication attemptAuthentication(
HttpServletRequest request, HttpServletResponse response)
- throws AuthenticationException, IOException, ServletException {
+ throws AuthenticationException, IOException {
final String token = tokenResolver.resolveAccessTokenOrNull(request);
@@ -80,14 +81,27 @@ protected void successfulAuthentication(
@Override
protected void unsuccessfulAuthentication(
HttpServletRequest request, HttpServletResponse response, AuthenticationException failed)
- throws IOException, ServletException {
+ throws IOException {
SecurityContextHolder.clearContext();
- log.info("Failed to process authentication request", failed);
- response.setStatus(((CustomAuthException) failed).getErrorCode().getStatus());
+ log.info("Failed to process authentication request: {}", failed.getMessage());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
+
+ if (failed instanceof CustomAuthException) {
+ response.setStatus(((CustomAuthException) failed).getErrorCode().getStatus());
+ try (OutputStream os = response.getOutputStream()) {
+ ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.writeValue(
+ os, ErrorResponse.of(((CustomAuthException) failed).getErrorCode()));
+ os.flush();
+ }
+ return;
+ }
+
+ // 일반 인증 실패에 대해서는 401로 응답하고 자세한 정보를 노출하지 않음
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
try (OutputStream os = response.getOutputStream()) {
ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.writeValue(os, ErrorResponse.of(((CustomAuthException) failed).getErrorCode()));
+ objectMapper.writeValue(os, ErrorResponse.of(ErrorCode.JWT_INVALID));
os.flush();
}
}
diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtilsTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtilsTest.java
index 31af7b3bf..ec504a0a8 100644
--- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtilsTest.java
+++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/CookieUtilsTest.java
@@ -8,7 +8,7 @@
import java.util.Optional;
import java.util.Set;
-import javax.servlet.http.Cookie;
+import jakarta.servlet.http.Cookie;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@@ -44,12 +44,13 @@ public void resolveCookieFromRequest() {
@Test
public void saveCookieToResponse() {
// given
+ MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
String cookieName = "myCookie";
String cookieContents = "hello";
// when
- CookieUtils.setCookie(response, cookieName, cookieContents, 180);
+ CookieUtils.setCookie(request, response, cookieName, cookieContents, 180);
// then
Cookie resolvedCookie = response.getCookie(cookieName);
@@ -83,7 +84,9 @@ public void removeCookieOfRequest() {
@DisplayName("성공적으로 serialize 한다.")
@Test
public void serializingTest()
- throws InvocationTargetException, InstantiationException, IllegalAccessException,
+ throws InvocationTargetException,
+ InstantiationException,
+ IllegalAccessException,
NoSuchMethodException {
// reflection
Constructor> constructor =
@@ -95,7 +98,7 @@ public void serializingTest()
OAuth2AuthorizationRequest.Builder builder =
(OAuth2AuthorizationRequest.Builder)
constructor.newInstance(AuthorizationGrantType.AUTHORIZATION_CODE);
- OAuth2AuthorizationRequest request =
+ OAuth2AuthorizationRequest requestObj =
builder
.authorizationUri("https://kauth.kakao.com/oauth/authorize")
.clientId("1234")
@@ -107,7 +110,7 @@ public void serializingTest()
.build();
// when
- String serializedRequest = CookieUtils.serialize(request);
+ String serializedRequest = CookieUtils.serialize(requestObj);
// then
assertTrue(Base64.isBase64(serializedRequest));
@@ -116,7 +119,9 @@ public void serializingTest()
@DisplayName("성공적으로 deserialize 한다.")
@Test
public void deserializingTest()
- throws NoSuchMethodException, InvocationTargetException, InstantiationException,
+ throws NoSuchMethodException,
+ InvocationTargetException,
+ InstantiationException,
IllegalAccessException {
// reflection
@@ -150,4 +155,56 @@ public void deserializingTest()
// then
assertThat(deserializedRequest).usingRecursiveComparison().isEqualTo(originalRequest);
}
+
+ @DisplayName("역직렬화 실패 시 null 반환한다.")
+ @Test
+ public void deserializeReturnsNullOnInvalidBase64OrPayload() {
+ // given
+ Cookie invalid = new Cookie("bad", "not_base64!!");
+
+ // when
+ OAuth2AuthorizationRequest result =
+ CookieUtils.deserialize(invalid, OAuth2AuthorizationRequest.class);
+
+ // then
+ assertThat(result).isNull();
+ }
+
+ @DisplayName("setCookie 시 SameSite=Lax 헤더를 추가한다.")
+ @Test
+ public void setCookieAddsSameSiteHeader() {
+ // given
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ // when
+ CookieUtils.setCookie(request, response, "s", "v", 60);
+
+ // then
+ java.util.List setCookies = response.getHeaders("Set-Cookie");
+ assertThat(setCookies).isNotEmpty();
+ assertThat(String.join(" ", setCookies)).contains("SameSite=Lax");
+ }
+
+ @DisplayName("deleteCookie 시 SameSite=Lax, Max-Age=0, HttpOnly를 포함한다.")
+ @Test
+ public void deleteCookieAddsAttributesProperly() {
+ // given
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ Cookie cookie = new Cookie("del", "bye");
+ cookie.setMaxAge(120);
+ request.setCookies(cookie);
+
+ // when
+ CookieUtils.deleteCookie(request, response, "del");
+
+ // then
+ java.util.List setCookies = response.getHeaders("Set-Cookie");
+ assertThat(setCookies).isNotEmpty();
+ String combined = String.join(" ", setCookies);
+ assertThat(combined).contains("SameSite=Lax");
+ assertThat(combined).contains("Max-Age=0");
+ assertThat(combined).contains("HttpOnly");
+ }
}
diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepositoryTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepositoryTest.java
index 1c8677a70..fbaee6c97 100644
--- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepositoryTest.java
+++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/cookie/HttpCookieOAuth2AuthorizationRequestRepositoryTest.java
@@ -10,7 +10,7 @@
import java.util.Set;
import java.util.function.Predicate;
-import javax.servlet.http.Cookie;
+import jakarta.servlet.http.Cookie;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandlerTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandlerTest.java
index b14405358..ba04a8591 100644
--- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandlerTest.java
+++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationFailureHandlerTest.java
@@ -6,7 +6,7 @@
import java.io.IOException;
-import javax.servlet.http.Cookie;
+import jakarta.servlet.http.Cookie;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandlerTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandlerTest.java
index 2bfaffcc4..ed99aeedd 100644
--- a/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandlerTest.java
+++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/oauth2/handler/Oauth2AuthenticationSuccessHandlerTest.java
@@ -12,7 +12,7 @@
import java.util.Map;
import java.util.Set;
-import javax.servlet.http.Cookie;
+import jakarta.servlet.http.Cookie;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenReIssueTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenReIssueTest.java
index 989014e7e..03725c85c 100644
--- a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenReIssueTest.java
+++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenReIssueTest.java
@@ -6,7 +6,7 @@
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.*;
-import javax.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequest;
import com.inhabas.api.auth.domain.token.exception.InvalidTokenException;
import com.inhabas.api.auth.domain.token.jwtUtils.JwtTokenReIssuer;
diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenUtilTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenUtilTest.java
index bf5cee8a8..06869c878 100644
--- a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenUtilTest.java
+++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/JwtTokenUtilTest.java
@@ -80,7 +80,7 @@ public void createJwtTokenTest() {
@Test
public void nullAuthenticationTokenTest() {
- assertThrows(AssertionError.class, () -> jwtTokenUtil.createAccessToken(null));
+ assertThrows(IllegalArgumentException.class, () -> jwtTokenUtil.createAccessToken(null));
}
@DisplayName("토큰을 정상적으로 decode")
diff --git a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/TokenAuthenticationProcessingFilterTest.java b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/TokenAuthenticationProcessingFilterTest.java
index caec1bdbd..193328fc4 100644
--- a/module-auth/src/test/java/com/inhabas/api/auth/domain/token/TokenAuthenticationProcessingFilterTest.java
+++ b/module-auth/src/test/java/com/inhabas/api/auth/domain/token/TokenAuthenticationProcessingFilterTest.java
@@ -20,10 +20,10 @@
// import java.util.HashMap;
// import java.util.List;
// import java.util.Map;
-// import javax.servlet.FilterChain;
-// import javax.servlet.ServletException;
-// import javax.servlet.http.HttpServletRequest;
-// import javax.servlet.http.HttpServletResponse;
+// import jakarta.servlet.FilterChain;
+// import jakarta.servlet.ServletException;
+// import jakarta.servlet.http.HttpServletRequest;
+// import jakarta.servlet.http.HttpServletResponse;
// import org.junit.jupiter.api.BeforeEach;
// import org.junit.jupiter.api.DisplayName;
// import org.junit.jupiter.api.Test;
diff --git a/module-jpa/src/main/java/com/inhabas/api/JpaConfig.java b/module-jpa/src/main/java/com/inhabas/api/JpaConfig.java
index 51b37774c..4e50fdaa7 100644
--- a/module-jpa/src/main/java/com/inhabas/api/JpaConfig.java
+++ b/module-jpa/src/main/java/com/inhabas/api/JpaConfig.java
@@ -1,7 +1,7 @@
package com.inhabas.api;
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/module-jpa/src/main/java/com/inhabas/api/sshTunneling/SshTunnelingInitializer.java b/module-jpa/src/main/java/com/inhabas/api/sshTunneling/SshTunnelingInitializer.java
index a65c42df0..b44664e93 100644
--- a/module-jpa/src/main/java/com/inhabas/api/sshTunneling/SshTunnelingInitializer.java
+++ b/module-jpa/src/main/java/com/inhabas/api/sshTunneling/SshTunnelingInitializer.java
@@ -4,8 +4,8 @@
import java.util.Properties;
-import javax.annotation.PreDestroy;
-import javax.validation.constraints.NotNull;
+import jakarta.annotation.PreDestroy;
+import jakarta.validation.constraints.NotNull;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
diff --git a/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java b/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java
index 664f68786..b6d8dd2ce 100644
--- a/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java
+++ b/resource-server/src/main/java/com/inhabas/api/config/SwaggerConfig.java
@@ -11,7 +11,7 @@
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import org.apache.http.HttpHeaders;
-import org.springdoc.core.GroupedOpenApi;
+import org.springdoc.core.models.GroupedOpenApi;
@Configuration
public class SwaggerConfig {
diff --git a/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java b/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java
index 9bdbee858..f5b9d36f2 100644
--- a/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java
+++ b/resource-server/src/main/java/com/inhabas/api/config/WebSecurityConfig.java
@@ -3,28 +3,36 @@
import static com.inhabas.api.auth.domain.oauth2.member.domain.valueObject.Role.*;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
+import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
-import org.springframework.security.access.expression.SecurityExpressionHandler;
-import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
-import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.ProviderManager;
+import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
-import org.springframework.security.web.FilterInvocation;
-import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
+import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.CorsUtils;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import com.inhabas.api.auth.config.AuthBeansConfig;
import com.inhabas.api.auth.domain.oauth2.member.security.Hierarchical;
@@ -42,10 +50,10 @@
public class WebSecurityConfig {
private static final String[] AUTH_WHITELIST_SWAGGER = {
- "/swagger-ui/**", "/swagger/**", "/docs/**"
+ "/swagger-ui/**", "/swagger/**", "/docs/**", "/v3/api-docs/**", "/swagger-resources/**"
};
private static final String[] AUTH_WHITELIST_STATIC = {
- "/static/css/**", "/static/js/**", "*.ico"
+ "/static/css/**", "/static/js/**", "/**/*.ico", "/favicon.ico"
};
private static final String[] AUTH_WHITELIST_TOKEN = {"/token/**"};
private static final String[] AUTH_WHITELIST_PATH = {
@@ -60,144 +68,170 @@ public class WebSecurityConfig {
"/club/activity/**", "/club/activities"
};
private static final String[] AUTH_WHITELIST_NORMAL_BOARD = {"/board/count"};
-
private static final String[] AUTH_WHITELIST_PROJECT_BOARD = {"/project/count"};
-
private static final String[] AUTH_WHITELIST_CONTEST_BOARD = {"/contest/count"};
- @Order(1)
- @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
+ @Configuration
+ @EnableMethodSecurity(jsr250Enabled = true)
@EnableWebSecurity
@RequiredArgsConstructor
@Profile({"local", "dev1", "dev2", "default_mvc_test", "prod1", "prod2", "integration_test"})
- public static class ApiSecurityForDev extends WebSecurityConfigurerAdapter {
+ public static class ApiSecurityForDev {
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
private final Hierarchical hierarchy;
private final JwtTokenUtil jwtTokenUtil;
- private final JwtAuthenticationProvider jwtAuthenticationProvider;
private final AuthBeansConfig authBeansConfig;
+ private final JwtAuthenticationProvider jwtAuthenticationProvider;
+
+ @Value("${cors.allowed-origins:*}")
+ private String allowedOriginsProp;
+
+ @Bean
+ public AuthenticationManager authenticationManager() {
+ return new ProviderManager(List.of(jwtAuthenticationProvider));
+ }
+
+ @Bean
+ public CorsConfigurationSource corsConfigurationSource() {
+ CorsConfiguration config = new CorsConfiguration();
+
+ List origins =
+ Arrays.stream(allowedOriginsProp.split(","))
+ .map(String::trim)
+ .filter(s -> !s.isEmpty())
+ .collect(Collectors.toList());
+
+ boolean wildcard = origins.contains("*");
+ if (wildcard) {
+ // 패턴 전체 허용 시, 자격 증명은 허용하지 않음 (보안 권장)
+ config.setAllowedOriginPatterns(List.of("*"));
+ config.setAllowCredentials(false);
+ } else {
+ config.setAllowedOrigins(origins);
+ config.setAllowCredentials(true);
+ }
+
+ config.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
+ config.setAllowedHeaders(List.of("*"));
+ config.setExposedHeaders(List.of("Authorization", "Content-Disposition"));
+ config.setMaxAge(3600L);
- @Override
- public void configure(AuthenticationManagerBuilder auth) throws Exception {
- auth.authenticationProvider(jwtAuthenticationProvider);
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", config);
+ return source;
}
- @Override
- public void configure(WebSecurity web) throws Exception {
- web.ignoring()
- .antMatchers(HttpMethod.GET, AUTH_WHITELIST_POLICY)
- .antMatchers(HttpMethod.GET, AUTH_WHITELIST_SIGNUP)
- .antMatchers(HttpMethod.GET, AUTH_WHITELIST_CLUB)
- .antMatchers(HttpMethod.GET, AUTH_WHITELIST_NORMAL_BOARD)
- .antMatchers(HttpMethod.GET, AUTH_WHITELIST_PROJECT_BOARD)
- .antMatchers(HttpMethod.GET, AUTH_WHITELIST_CONTEST_BOARD)
- .antMatchers(AUTH_WHITELIST_SWAGGER)
- .antMatchers(AUTH_WHITELIST_STATIC)
- .antMatchers(AUTH_WHITELIST_PATH);
+ @Bean
+ public WebSecurityCustomizer webSecurityCustomizer() {
+ return (web) -> {};
}
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http
- // OAuth 관련 경로 제외 모든 경로
- .requestMatchers()
- .antMatchers("/**")
- .and()
- .anonymous()
- .authorities("ROLE_" + ANONYMOUS)
- .and()
- // HTTP 기본 인증 비활성화
- .httpBasic()
- .disable()
- // 세션 생성 금지
- .sessionManagement()
- .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
- .and()
- // API 이므로 CORS 활성화, CSRF 비활성화
- .cors()
- .and()
- .csrf()
- .disable()
-
- // 인증 예외 처리시 jwtAuthenticationEntryPoint 사용
- .exceptionHandling()
- .authenticationEntryPoint(jwtAuthenticationEntryPoint)
- .accessDeniedHandler(jwtAccessDeniedHandler)
- .and()
- .authorizeRequests()
- // 권한 부여 표현식
- .expressionHandler(expressionHandler())
- // Preflight 방식
- .requestMatchers(CorsUtils::isPreFlightRequest)
- .permitAll()
- .antMatchers("/myInfo/requests")
- .hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString())
- .antMatchers("/myInfo/request/**")
- .hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString())
-
- // 회원 관리
- .antMatchers("/members/executive")
- .hasRole(ANONYMOUS.toString())
- .antMatchers("/members/hof")
- .hasRole(DEACTIVATED.toString())
- .antMatchers("/members/approved/role")
- .hasRole(SECRETARY.toString())
- .antMatchers("/members/approved/type")
- .hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString())
- .antMatchers("/members/**", "/member/**")
- .hasAnyRole(SECRETARY.toString(), EXECUTIVES.toString())
- // 회계내역
- .antMatchers(
- "/budget/history/**",
- "/budget/histories",
- "/budget/application/**",
- "/budget/applications")
- .hasRole(DEACTIVATED.toString())
- // 강의
- .antMatchers("/lecture/**/status")
- .hasRole(EXECUTIVES.toString())
- .antMatchers("/lecture/**")
- .hasRole(DEACTIVATED.toString())
-
- // 회원가입 일정 수정
- .antMatchers(HttpMethod.PUT, "/signUp/schedule")
- .hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString())
-
- // 회원가입은 ANONYMOUS 권한은 명시적으로 부여받은 상태에서만 가능
- .antMatchers("/signUp/check")
- .hasRole(ANONYMOUS.toString())
- .antMatchers("/signUp/**")
- .hasRole(SIGNING_UP.toString())
-
- // 동아리 연혁 수정
- .antMatchers("/club/history/**")
- .hasRole(EXECUTIVES.toString())
-
- // 정책 수정
- .antMatchers(HttpMethod.PUT, "/policy/**")
- .hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString())
-
- // 장학회 연혁 수정
- .antMatchers("/scholarship/history/**")
- .hasRole(SECRETARY.toString())
-
- // 그 외
- .anyRequest()
- .hasRole(ANONYMOUS.toString());
+ @Bean
+ @Order(1)
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ http.anonymous(
+ anonymous -> anonymous.principal("anonymousUser").authorities("ROLE_" + ANONYMOUS))
+ .httpBasic(httpBasic -> httpBasic.disable())
+ .sessionManagement(
+ sessionManagement ->
+ sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+ .cors(cors -> cors.configurationSource(corsConfigurationSource()))
+ .csrf(AbstractHttpConfigurer::disable)
+ .headers(
+ headers ->
+ headers
+ .referrerPolicy(
+ r -> r.policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.NO_REFERRER))
+ .frameOptions(frame -> frame.sameOrigin()))
+ .exceptionHandling(
+ exceptionHandling ->
+ exceptionHandling
+ .authenticationEntryPoint(jwtAuthenticationEntryPoint)
+ .accessDeniedHandler(jwtAccessDeniedHandler))
+ .authorizeHttpRequests(
+ authorize ->
+ authorize
+ .requestMatchers(CorsUtils::isPreFlightRequest)
+ .permitAll()
+ // Swagger 및 공개 경로는 필터 체인은 타되 인가만 면제
+ .requestMatchers(pathMatchers(AUTH_WHITELIST_SWAGGER))
+ .permitAll()
+ .requestMatchers(pathMatchers(AUTH_WHITELIST_STATIC))
+ .permitAll()
+ .requestMatchers(pathMatchers(AUTH_WHITELIST_PATH))
+ .permitAll()
+ // GET 공개 엔드포인트들
+ .requestMatchers(methodMatchers(HttpMethod.GET, AUTH_WHITELIST_POLICY))
+ .permitAll()
+ .requestMatchers(methodMatchers(HttpMethod.GET, AUTH_WHITELIST_SIGNUP))
+ .permitAll()
+ .requestMatchers(methodMatchers(HttpMethod.GET, AUTH_WHITELIST_CLUB))
+ .permitAll()
+ .requestMatchers(methodMatchers(HttpMethod.GET, AUTH_WHITELIST_NORMAL_BOARD))
+ .permitAll()
+ .requestMatchers(methodMatchers(HttpMethod.GET, AUTH_WHITELIST_PROJECT_BOARD))
+ .permitAll()
+ .requestMatchers(methodMatchers(HttpMethod.GET, AUTH_WHITELIST_CONTEST_BOARD))
+ .permitAll()
+ // 나머지 기존 인가 규칙 유지
+ .requestMatchers(pathMatchers("/myInfo/requests"))
+ .hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString())
+ .requestMatchers(pathMatchers("/myInfo/request/**"))
+ .hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString())
+ .requestMatchers(pathMatchers("/members/executive"))
+ .hasRole(ANONYMOUS.toString())
+ .requestMatchers(pathMatchers("/members/hof"))
+ .hasRole(DEACTIVATED.toString())
+ .requestMatchers(pathMatchers("/members/approved/role"))
+ .hasRole(SECRETARY.toString())
+ .requestMatchers(pathMatchers("/members/approved/type"))
+ .hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString())
+ .requestMatchers(pathMatchers("/members/**", "/member/**"))
+ .hasAnyRole(SECRETARY.toString(), EXECUTIVES.toString())
+ .requestMatchers(
+ pathMatchers(
+ "/budget/history/**",
+ "/budget/histories",
+ "/budget/application/**",
+ "/budget/applications"))
+ .hasRole(DEACTIVATED.toString())
+ .requestMatchers(pathMatchers("/lecture/**/status"))
+ .hasRole(EXECUTIVES.toString())
+ .requestMatchers(pathMatchers("/lecture/**"))
+ .hasRole(DEACTIVATED.toString())
+ .requestMatchers(methodMatchers(HttpMethod.PUT, "/signUp/schedule"))
+ .hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString())
+ .requestMatchers(pathMatchers("/signUp/check"))
+ .hasAnyRole(ANONYMOUS.toString(), SIGNING_UP.toString())
+ .requestMatchers(pathMatchers("/signUp/**"))
+ .hasRole(SIGNING_UP.toString())
+ .requestMatchers(pathMatchers("/club/history/**"))
+ .hasRole(EXECUTIVES.toString())
+ .requestMatchers(methodMatchers(HttpMethod.PUT, "/policy/**"))
+ .hasAnyRole(CHIEF.toString(), VICE_CHIEF.toString())
+ .requestMatchers(pathMatchers("/scholarship/history/**"))
+ .hasRole(SECRETARY.toString())
+ .anyRequest()
+ .hasRole(ANONYMOUS.toString()));
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
+
+ return http.build();
}
- @Bean
- public SecurityExpressionHandler expressionHandler() {
- DefaultWebSecurityExpressionHandler webSecurityExpressionHandler =
- new DefaultWebSecurityExpressionHandler();
- webSecurityExpressionHandler.setRoleHierarchy(hierarchy.getHierarchy());
- return webSecurityExpressionHandler;
+ private static RequestMatcher[] pathMatchers(String... patterns) {
+ return Arrays.stream(patterns).map(AntPathRequestMatcher::new).toArray(RequestMatcher[]::new);
+ }
+
+ private static RequestMatcher[] methodMatchers(HttpMethod method, String... patterns) {
+ return Arrays.stream(patterns)
+ .map(p -> new AntPathRequestMatcher(p, method.name()))
+ .toArray(RequestMatcher[]::new);
}
+ @Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
final List skipPaths = new ArrayList<>();
@@ -213,8 +247,7 @@ public JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
final JwtAuthenticationFilter filter =
new JwtAuthenticationFilter(
requestMatcher, jwtTokenUtil, authBeansConfig.tokenResolver());
-
- filter.setAuthenticationManager(super.authenticationManager());
+ filter.setAuthenticationManager(authenticationManager());
return filter;
}
}
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/BaseEntity.java b/resource-server/src/main/java/com/inhabas/api/domain/BaseEntity.java
index b70b337df..e756cd31a 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/BaseEntity.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/BaseEntity.java
@@ -2,9 +2,9 @@
import java.time.LocalDateTime;
-import javax.persistence.Column;
-import javax.persistence.EntityListeners;
-import javax.persistence.MappedSuperclass;
+import jakarta.persistence.Column;
+import jakarta.persistence.EntityListeners;
+import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java
index 0afe1347e..4f66cbd8d 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/AlbumBoard.java
@@ -3,7 +3,7 @@
import java.util.ArrayList;
import java.util.List;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/BaseBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/BaseBoard.java
index 7fa8cedd6..478bf5436 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/BaseBoard.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/BaseBoard.java
@@ -4,7 +4,7 @@
import java.util.List;
import java.util.Objects;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Content.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Content.java
index 47f6142fc..3736107b1 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Content.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Content.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import com.inhabas.api.auth.domain.error.businessException.InvalidInputException;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Title.java b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Title.java
index 70b938e9d..c8aee22e7 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Title.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/board/domain/valueObject/Title.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardCountDto.java b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardCountDto.java
index fc56c03d0..e092a0ec2 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardCountDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/board/dto/BoardCountDto.java
@@ -1,7 +1,7 @@
package com.inhabas.api.domain.board.dto;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.PositiveOrZero;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.PositiveOrZero;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardSecurityChecker.java b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardSecurityChecker.java
index 31ae7a515..adf41216d 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardSecurityChecker.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/board/usecase/BoardSecurityChecker.java
@@ -9,7 +9,7 @@
import java.util.Set;
import java.util.stream.Collectors;
-import javax.persistence.EntityNotFoundException;
+import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetHistory.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetHistory.java
index 51f75f9af..635be4df8 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetHistory.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetHistory.java
@@ -2,7 +2,7 @@
import java.time.LocalDateTime;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetSupportApplication.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetSupportApplication.java
index b0a4b2b2e..d7f4d8069 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetSupportApplication.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/BudgetSupportApplication.java
@@ -2,7 +2,7 @@
import java.time.LocalDateTime;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Account.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Account.java
index ba1115877..4b7b113f8 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Account.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Account.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Details.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Details.java
index 0f957f08c..da90d2b05 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Details.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Details.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Price.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Price.java
index 1815937ba..7a41ee0d9 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Price.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/Price.java
@@ -2,8 +2,8 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/RejectReason.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/RejectReason.java
index bdb01ffc9..13627149c 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/RejectReason.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/domain/valueObject/RejectReason.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationDetailDto.java
index 2fa69a266..eb522b86c 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationDetailDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationDetailDto.java
@@ -3,10 +3,10 @@
import java.time.LocalDateTime;
import java.util.List;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Past;
-import javax.validation.constraints.PositiveOrZero;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Past;
+import jakarta.validation.constraints.PositiveOrZero;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationDto.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationDto.java
index 892ad24bb..6ecfc7937 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationDto.java
@@ -2,8 +2,8 @@
import java.time.LocalDateTime;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationRegisterForm.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationRegisterForm.java
index 04d984e47..c0a6f0f7e 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationRegisterForm.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationRegisterForm.java
@@ -4,11 +4,11 @@
import java.util.ArrayList;
import java.util.List;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Past;
-import javax.validation.constraints.PositiveOrZero;
-import javax.validation.constraints.Size;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Past;
+import jakarta.validation.constraints.PositiveOrZero;
+import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Builder;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationStatusChangeRequest.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationStatusChangeRequest.java
index 4e8af9c7e..03b412605 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationStatusChangeRequest.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetApplicationStatusChangeRequest.java
@@ -1,6 +1,6 @@
package com.inhabas.api.domain.budget.dto;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotNull;
import lombok.AccessLevel;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryCreateForm.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryCreateForm.java
index 280a4b0ae..c03c3c6a4 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryCreateForm.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryCreateForm.java
@@ -3,11 +3,11 @@
import java.time.LocalDateTime;
import java.util.List;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Past;
-import javax.validation.constraints.PositiveOrZero;
-import javax.validation.constraints.Size;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Past;
+import jakarta.validation.constraints.PositiveOrZero;
+import jakarta.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Builder;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryDetailDto.java
index 83ff4972e..3b3352cdc 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryDetailDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryDetailDto.java
@@ -3,10 +3,10 @@
import java.time.LocalDateTime;
import java.util.List;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Past;
-import javax.validation.constraints.PositiveOrZero;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Past;
+import jakarta.validation.constraints.PositiveOrZero;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryDto.java b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryDto.java
index ce51b0009..a0e918431 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/budget/dto/BudgetHistoryDto.java
@@ -2,10 +2,10 @@
import java.time.LocalDateTime;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Past;
-import javax.validation.constraints.PositiveOrZero;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Past;
+import jakarta.validation.constraints.PositiveOrZero;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/domain/ClubHistory.java b/resource-server/src/main/java/com/inhabas/api/domain/club/domain/ClubHistory.java
index 12bebf6a7..67785f28c 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/club/domain/ClubHistory.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/club/domain/ClubHistory.java
@@ -2,7 +2,7 @@
import java.time.LocalDateTime;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDetailDto.java
index 153d4e9fa..a8aa86006 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDetailDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDetailDto.java
@@ -3,9 +3,9 @@
import java.time.LocalDateTime;
import java.util.List;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDto.java b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDto.java
index 64e80c3e1..e1e1875aa 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubActivityDto.java
@@ -2,9 +2,9 @@
import java.time.LocalDateTime;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubHistoryDto.java b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubHistoryDto.java
index d7edf8dde..bc3c25a60 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubHistoryDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/ClubHistoryDto.java
@@ -2,8 +2,8 @@
import java.time.LocalDateTime;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubActivityDto.java b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubActivityDto.java
index 8e677ec36..5c5452ae4 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubActivityDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubActivityDto.java
@@ -3,9 +3,9 @@
import java.util.ArrayList;
import java.util.List;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubHistoryDto.java b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubHistoryDto.java
index 1f2b7d83b..db93b4b26 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubHistoryDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/club/dto/SaveClubHistoryDto.java
@@ -2,7 +2,7 @@
import java.time.LocalDateTime;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/Comment.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/Comment.java
index d73110d7c..30d169f4e 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/Comment.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/Comment.java
@@ -5,7 +5,7 @@
import java.util.List;
import java.util.Objects;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/valueObject/Content.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/valueObject/Content.java
index fd9921058..a3d6621bf 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/valueObject/Content.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/domain/valueObject/Content.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import com.inhabas.api.auth.domain.error.businessException.InvalidInputException;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentDetailDto.java
index 0d559137a..65983a45b 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentDetailDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentDetailDto.java
@@ -4,9 +4,9 @@
import java.util.ArrayList;
import java.util.List;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
import lombok.Getter;
import lombok.NoArgsConstructor;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentSaveDto.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentSaveDto.java
index 1e1f4dde6..dc7294729 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentSaveDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentSaveDto.java
@@ -1,7 +1,7 @@
package com.inhabas.api.domain.comment.dto;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.Positive;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Positive;
import lombok.AccessLevel;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentUpdateDto.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentUpdateDto.java
index 639f9685d..c63cba208 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentUpdateDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/CommentUpdateDto.java
@@ -1,6 +1,6 @@
package com.inhabas.api.domain.comment.dto;
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
import lombok.AccessLevel;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/WriterInfo.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/WriterInfo.java
index e82badc6c..73a932806 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/WriterInfo.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/dto/WriterInfo.java
@@ -1,8 +1,8 @@
package com.inhabas.api.domain.comment.dto;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
import lombok.Getter;
import lombok.NoArgsConstructor;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/comment/usecase/CommentServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/comment/usecase/CommentServiceImpl.java
index e59960593..e2cf99952 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/comment/usecase/CommentServiceImpl.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/comment/usecase/CommentServiceImpl.java
@@ -2,7 +2,7 @@
import java.util.List;
-import javax.persistence.EntityManager;
+import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java
index 438e152a7..1a56d723c 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestBoard.java
@@ -7,17 +7,17 @@
import java.util.Collections;
import java.util.List;
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.DiscriminatorValue;
-import javax.persistence.Embedded;
-import javax.persistence.Entity;
-import javax.persistence.EntityListeners;
-import javax.persistence.ForeignKey;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.DiscriminatorValue;
+import jakarta.persistence.Embedded;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EntityListeners;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Builder;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestField.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestField.java
index a9200a0d4..c132f0341 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestField.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/ContestField.java
@@ -1,13 +1,13 @@
package com.inhabas.api.domain.contest.domain;
-import javax.persistence.Column;
-import javax.persistence.Embedded;
-import javax.persistence.Entity;
-import javax.persistence.EntityListeners;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embedded;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EntityListeners;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Builder;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Association.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Association.java
index 12e82d2db..3d3117610 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Association.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Association.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import com.inhabas.api.auth.domain.error.businessException.InvalidInputException;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/ContestFieldName.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/ContestFieldName.java
index 85e45a708..4c2e362d1 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/ContestFieldName.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/ContestFieldName.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import com.inhabas.api.auth.domain.error.businessException.InvalidInputException;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Topic.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Topic.java
index fde048d86..8200da5cf 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Topic.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/domain/valueObject/Topic.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import com.inhabas.api.auth.domain.error.businessException.InvalidInputException;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/ContestBoardDetailDto.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/ContestBoardDetailDto.java
index f31d5b201..ef650abc4 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/ContestBoardDetailDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/ContestBoardDetailDto.java
@@ -3,9 +3,9 @@
import java.time.LocalDateTime;
import java.util.List;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/ContestBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/ContestBoardDto.java
index 937e38f28..efa2c0fbb 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/ContestBoardDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/ContestBoardDto.java
@@ -2,9 +2,9 @@
import java.time.LocalDateTime;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Positive;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/SaveContestBoardDto.java b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/SaveContestBoardDto.java
index 71ea46aa7..182d5b19c 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/SaveContestBoardDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/contest/dto/SaveContestBoardDto.java
@@ -4,10 +4,10 @@
import java.util.ArrayList;
import java.util.List;
-import javax.validation.constraints.Future;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
+import jakarta.validation.constraints.Future;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BaseFile.java b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BaseFile.java
index c4bea7a80..6f9bf328f 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BaseFile.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BaseFile.java
@@ -3,7 +3,7 @@
import java.time.LocalDateTime;
import java.util.Objects;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BoardFile.java b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BoardFile.java
index ee39f16dc..21e683672 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BoardFile.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/BoardFile.java
@@ -2,7 +2,7 @@
import java.util.Objects;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileName.java b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileName.java
index 179524b1a..12dd1c2ae 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileName.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileName.java
@@ -4,9 +4,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import com.inhabas.api.auth.domain.error.businessException.InvalidInputException;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileUrl.java b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileUrl.java
index 296e9f5cf..8ee8fbe1d 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileUrl.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/file/domain/valueObject/FileUrl.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import com.inhabas.api.auth.domain.error.businessException.InvalidInputException;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/file/dto/FileDownloadDto.java b/resource-server/src/main/java/com/inhabas/api/domain/file/dto/FileDownloadDto.java
index 1e7636954..8af72855d 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/file/dto/FileDownloadDto.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/file/dto/FileDownloadDto.java
@@ -1,7 +1,7 @@
package com.inhabas.api.domain.file.dto;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Lecture.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Lecture.java
index c8e449ae7..010f874d0 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Lecture.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Lecture.java
@@ -2,9 +2,9 @@
import java.time.LocalDateTime;
-import javax.persistence.*;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
+import jakarta.persistence.*;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
import lombok.AccessLevel;
import lombok.Builder;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Student.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Student.java
index ce7ccdcfc..2e338a333 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Student.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/Student.java
@@ -1,6 +1,6 @@
package com.inhabas.api.domain.lecture.domain;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/LectureStatusConverter.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/LectureStatusConverter.java
index 2cba4d2bd..1a5404371 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/LectureStatusConverter.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/LectureStatusConverter.java
@@ -2,8 +2,8 @@
import java.util.Objects;
-import javax.persistence.AttributeConverter;
-import javax.persistence.Converter;
+import jakarta.persistence.AttributeConverter;
+import jakarta.persistence.Converter;
import com.inhabas.api.domain.lecture.domain.valueObject.LectureStatus;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/StudentStatusConverter.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/StudentStatusConverter.java
index 2ae1ea6fa..ca284364f 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/StudentStatusConverter.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/domain/converter/StudentStatusConverter.java
@@ -2,7 +2,7 @@
import java.util.Objects;
-import javax.persistence.AttributeConverter;
+import jakarta.persistence.AttributeConverter;
import com.inhabas.api.domain.lecture.domain.valueObject.StudentStatus;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureRegisterForm.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureRegisterForm.java
index 631672e15..ed8a1d478 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureRegisterForm.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureRegisterForm.java
@@ -2,9 +2,9 @@
import java.time.LocalDateTime;
-import javax.validation.constraints.Future;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.Future;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
import lombok.AccessLevel;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureStatusUpdateRequest.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureStatusUpdateRequest.java
index 55d62e3b0..aa8e3cde6 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureStatusUpdateRequest.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureStatusUpdateRequest.java
@@ -1,6 +1,6 @@
package com.inhabas.api.domain.lecture.dto;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotNull;
import lombok.AccessLevel;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureUpdateForm.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureUpdateForm.java
index fbfadef40..a283cfd06 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureUpdateForm.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/dto/LectureUpdateForm.java
@@ -1,6 +1,6 @@
package com.inhabas.api.domain.lecture.dto;
-import javax.validation.constraints.NotNull;
+import jakarta.validation.constraints.NotNull;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureSecurityChecker.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureSecurityChecker.java
index 6aeeb8c9e..b616c1bc5 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureSecurityChecker.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureSecurityChecker.java
@@ -1,6 +1,6 @@
package com.inhabas.api.domain.lecture.usecase;
-import javax.persistence.EntityNotFoundException;
+import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureServiceImpl.java
index a18b9be3a..a5587ce64 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureServiceImpl.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureServiceImpl.java
@@ -1,6 +1,6 @@
package com.inhabas.api.domain.lecture.usecase;
-import javax.persistence.EntityNotFoundException;
+import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceImpl.java
index f2e2e0a2c..40ef37540 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceImpl.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/lecture/usecase/LectureStudentServiceImpl.java
@@ -5,7 +5,7 @@
import java.util.Set;
import java.util.stream.Collectors;
-import javax.persistence.EntityNotFoundException;
+import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/Menu.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/Menu.java
index 87ff7c8d7..220bdb5b5 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/Menu.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/Menu.java
@@ -1,6 +1,6 @@
package com.inhabas.api.domain.menu.domain;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/MenuGroup.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/MenuGroup.java
index 62c1fd129..3507b9d1e 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/MenuGroup.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/MenuGroup.java
@@ -1,6 +1,6 @@
package com.inhabas.api.domain.menu.domain;
-import javax.persistence.*;
+import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/Description.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/Description.java
index 17387fbe0..e8ecdcbff 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/Description.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/Description.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupName.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupName.java
index 7685ad32f..329e6938a 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupName.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuGroupName.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
@Embeddable
public class MenuGroupName {
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuId.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuId.java
index baef2f476..87e377d4c 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuId.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuId.java
@@ -3,10 +3,10 @@
import java.io.Serializable;
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuName.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuName.java
index f38f60849..e02489941 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuName.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/domain/valueObject/MenuName.java
@@ -2,9 +2,9 @@
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.Transient;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.Transient;
@Embeddable
public class MenuName {
diff --git a/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepositoryImpl.java b/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepositoryImpl.java
index d66d02255..44cfdb9e7 100644
--- a/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepositoryImpl.java
+++ b/resource-server/src/main/java/com/inhabas/api/domain/menu/repository/MenuRepositoryImpl.java
@@ -1,9 +1,11 @@
package com.inhabas.api.domain.menu.repository;
import static com.inhabas.api.domain.menu.domain.QMenu.menu;
-import static com.querydsl.core.group.GroupBy.list;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
@@ -13,8 +15,6 @@
import com.inhabas.api.domain.menu.domain.valueObject.MenuId;
import com.inhabas.api.domain.menu.dto.MenuDto;
import com.inhabas.api.domain.menu.dto.MenuGroupDto;
-import com.querydsl.core.group.GroupBy;
-import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
@RequiredArgsConstructor
@@ -23,28 +23,35 @@ public class MenuRepositoryImpl implements MenuRepositoryCustom {
private final JPAQueryFactory jpaQueryFactory;
public List findAllMenuByMenuGroup() {
- return jpaQueryFactory
- .from(menu)
- .orderBy(menu.menuGroup.id.asc())
- .orderBy(menu.priority.asc())
- .transform(
- GroupBy.groupBy(menu.menuGroup)
- .as(
- list(
- Projections.constructor(
- MenuDto.class,
- menu.id,
- menu.priority,
- menu.name.value,
- menu.type, // enum type
- menu.description.value))))
- .entrySet()
- .stream()
- .map(
- entry ->
- new MenuGroupDto(
- entry.getKey().getId(), entry.getKey().getName(), entry.getValue()))
- .collect(Collectors.toList());
+ // Hibernate 6 호환: transform/ScrollableResults 없이 한 번에 조회 후 Java에서 그룹핑
+ List