diff --git a/build.gradle.kts b/build.gradle.kts index 61533ecf..7ef45fd0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -28,14 +28,13 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-validation") implementation("org.springframework.boot:spring-boot-starter-web") - + implementation("io.github.cdimascio:java-dotenv:5.2.2") implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-oauth2-client") implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0") implementation("io.jsonwebtoken:jjwt-api:0.12.3") runtimeOnly("io.jsonwebtoken:jjwt-impl:0.12.3") runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.12.3") - implementation("me.paulschwarz:spring-dotenv:4.0.0") compileOnly("org.projectlombok:lombok") developmentOnly("org.springframework.boot:spring-boot-devtools") runtimeOnly("com.h2database:h2") diff --git a/src/main/java/com/back/BackApplication.java b/src/main/java/com/back/BackApplication.java index 530c84fc..87ac32bb 100644 --- a/src/main/java/com/back/BackApplication.java +++ b/src/main/java/com/back/BackApplication.java @@ -1,5 +1,6 @@ package com.back; +import io.github.cdimascio.dotenv.Dotenv; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; @@ -9,6 +10,11 @@ public class BackApplication { public static void main(String[] args) { + Dotenv dotenv = Dotenv.load(); + System.out.println("KAKAO_OAUTH2_CLIENT_ID: " + dotenv.get("KAKAO_OAUTH2_CLIENT_ID")); + System.out.println("GOOGLE_OAUTH2_CLIENT_ID: " + dotenv.get("GOOGLE_OAUTH2_CLIENT_ID")); + System.out.println("NAVER_OAUTH2_CLIENT_ID: " + dotenv.get("NAVER_OAUTH2_CLIENT_ID")); + SpringApplication.run(BackApplication.class, args); } diff --git a/src/main/java/com/back/domain/user/entity/User.java b/src/main/java/com/back/domain/user/entity/User.java index 036d95d2..4e8c5d43 100644 --- a/src/main/java/com/back/domain/user/entity/User.java +++ b/src/main/java/com/back/domain/user/entity/User.java @@ -33,6 +33,10 @@ public class User { @Column(nullable = false, unique = true, length = 50) private String nickname; // 고유 닉네임 + // OAuth2 관련 필드 + @Column(unique = true, length = 100) + private String oauthId; // OAuth 제공자별 고유 ID (예: kakao_123456789) + private Double abvDegree; // 알콜도수(회원 등급) @CreatedDate // JPA Auditing 적용 diff --git a/src/main/java/com/back/domain/user/repository/UserRepository.java b/src/main/java/com/back/domain/user/repository/UserRepository.java index 040d5ef1..a05f0199 100644 --- a/src/main/java/com/back/domain/user/repository/UserRepository.java +++ b/src/main/java/com/back/domain/user/repository/UserRepository.java @@ -4,8 +4,14 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface UserRepository extends JpaRepository { + + Optional findByOauthId(String oauthId); + Optional findByEmail(String email); + Optional findByNickname(String nickname); boolean existsByNicknameAndIdNot(String nickname, Long id); } diff --git a/src/main/java/com/back/domain/user/service/UserService.java b/src/main/java/com/back/domain/user/service/UserService.java index 103c5a97..3555a62e 100644 --- a/src/main/java/com/back/domain/user/service/UserService.java +++ b/src/main/java/com/back/domain/user/service/UserService.java @@ -2,10 +2,15 @@ import com.back.domain.user.entity.User; import com.back.domain.user.repository.UserRepository; +import com.back.global.exception.ServiceException; +import com.back.global.rsData.RsData; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; +import java.util.Optional; + @Service @RequiredArgsConstructor public class UserService { @@ -17,4 +22,61 @@ public User findById(Long id) { return userRepository.findById(id) .orElseThrow(() -> new IllegalArgumentException("User not found. id=" + id)); } + + + public User joinSocial(String oauthId, String email, String nickname){ + userRepository.findByOauthId(oauthId) + .ifPresent(user -> { + throw new ServiceException(409, "이미 존재하는 계정입니다."); + }); + + // 고유한 닉네임 생성 + String uniqueNickname = generateUniqueNickname(nickname); + + User user = User.builder() + .email(email) + .nickname(uniqueNickname) + .abvDegree(0.0) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .role("USER") + .oauthId(oauthId) + .build(); + + return userRepository.save(user); + } + + @Transactional + public RsData findOrCreateOAuthUser(String oauthId, String email, String nickname) { + Optional existingUser = userRepository.findByOauthId(oauthId); + + if (existingUser.isPresent()) { + // 기존 사용자 업데이트 (이메일만 업데이트) + User user = existingUser.get(); + user.setEmail(email); + return RsData.of(200, "회원 정보가 업데이트 되었습니다", user); //더티체킹 + } else { + User newUser = joinSocial(oauthId, email, nickname); + return RsData.of(201, "사용자가 생성되었습니다", newUser); + } + } + + public String generateUniqueNickname(String baseNickname) { + // null이거나 빈 문자열인 경우 기본값 설정 + if (baseNickname == null || baseNickname.trim().isEmpty()) { + baseNickname = "User"; + } + + String nickname = baseNickname; + int counter = 1; + + // 중복 체크 및 고유한 닉네임 생성 + while (userRepository.findByNickname(nickname).isPresent()) { + nickname = baseNickname + counter; + counter++; + } + + return nickname; + } + } \ No newline at end of file diff --git a/src/main/java/com/back/global/rq/Rq.java b/src/main/java/com/back/global/rq/Rq.java index db4abc93..ba09f564 100644 --- a/src/main/java/com/back/global/rq/Rq.java +++ b/src/main/java/com/back/global/rq/Rq.java @@ -8,6 +8,7 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; +import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseCookie; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; @@ -24,6 +25,9 @@ public class Rq { private final HttpServletResponse resp; private final UserService userService; + @Value("${custom.cookie.secure:false}") + private boolean cookieSecure; + public User getActor() { return Optional.ofNullable( SecurityContextHolder @@ -85,7 +89,7 @@ public void setCrossDomainCookie(String name, String value, int maxAge) { ResponseCookie cookie = ResponseCookie.from(name, value) .path("/") .maxAge(maxAge) - .secure(true) + .secure(cookieSecure) .sameSite("None") .httpOnly(true) .build(); diff --git a/src/main/java/com/back/global/security/CustomAuthenticationFilter.java b/src/main/java/com/back/global/security/CustomAuthenticationFilter.java index 621230d1..a79a7907 100644 --- a/src/main/java/com/back/global/security/CustomAuthenticationFilter.java +++ b/src/main/java/com/back/global/security/CustomAuthenticationFilter.java @@ -19,6 +19,7 @@ import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; +import java.util.Map; @Component @RequiredArgsConstructor @@ -54,9 +55,9 @@ private void work(HttpServletRequest request, HttpServletResponse response, Filt if ( //추후 로그인 필요한 api 추가 설정 uri.startsWith("/h2-console") || - uri.startsWith("/api/login/oauth2/") || - (method.equals("GET") && uri.equals("api/~~")) || - (method.equals("POST") && uri.equals("/api/user/login")) + uri.startsWith("/login/oauth2/") || + (method.equals("GET") && uri.equals("/api/~~")) || + (method.equals("POST") && uri.equals("/api/~")) ) { filterChain.doFilter(request, response); @@ -120,8 +121,8 @@ private void work(HttpServletRequest request, HttpServletResponse response, Filt user.getId(), user.getEmail(), user.getNickname(), - "", - user.getAuthorities() + user.getAuthorities(), + Map.of() // JWT 인증에서는 빈 attributes ); Authentication authentication = new UsernamePasswordAuthenticationToken( userDetails, diff --git a/src/main/java/com/back/global/security/CustomOAuth2AuthorizationRequestResolver.java b/src/main/java/com/back/global/security/CustomOAuth2AuthorizationRequestResolver.java new file mode 100644 index 00000000..944b6707 --- /dev/null +++ b/src/main/java/com/back/global/security/CustomOAuth2AuthorizationRequestResolver.java @@ -0,0 +1,62 @@ +package com.back.global.security; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizationRequestResolver; +import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter; +import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver; +import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; +import org.springframework.stereotype.Component; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.UUID; + +@Component +@RequiredArgsConstructor +public class CustomOAuth2AuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver { + + private final ClientRegistrationRepository clientRegistrationRepository; + + private DefaultOAuth2AuthorizationRequestResolver createDefaultResolver() { + // Spring Security 기본 Authorization URI 사용 + return new DefaultOAuth2AuthorizationRequestResolver( + clientRegistrationRepository, + OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + ); + } + + @Override + public OAuth2AuthorizationRequest resolve(HttpServletRequest request) { + OAuth2AuthorizationRequest req = createDefaultResolver().resolve(request); + return customizeState(req, request); + } + + @Override + public OAuth2AuthorizationRequest resolve(HttpServletRequest request, String clientRegistrationId) { + OAuth2AuthorizationRequest req = createDefaultResolver().resolve(request, clientRegistrationId); + return customizeState(req, request); + } + + private OAuth2AuthorizationRequest customizeState(OAuth2AuthorizationRequest req, HttpServletRequest request) { + if (req == null) return null; + + // 요청 파라미터에서 redirectUrl 가져오기 + String redirectUrl = request.getParameter("redirectUrl"); + if (redirectUrl == null) redirectUrl = "/"; + + // CSRF 방지용 nonce 추가 + String originState = UUID.randomUUID().toString(); + + // redirectUrl#originState 결합 + String rawState = redirectUrl + "#" + originState; + + // Base64 URL-safe 인코딩 + String encodedState = Base64.getUrlEncoder().encodeToString(rawState.getBytes(StandardCharsets.UTF_8)); + + return OAuth2AuthorizationRequest.from(req) + .state(encodedState) // state 교체 + .build(); + } +} diff --git a/src/main/java/com/back/global/security/CustomOAuth2LoginFailureHandler.java b/src/main/java/com/back/global/security/CustomOAuth2LoginFailureHandler.java new file mode 100644 index 00000000..395380a2 --- /dev/null +++ b/src/main/java/com/back/global/security/CustomOAuth2LoginFailureHandler.java @@ -0,0 +1,32 @@ +package com.back.global.security; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +@Slf4j +public class CustomOAuth2LoginFailureHandler implements AuthenticationFailureHandler { + + @Value("${FRONTEND_URL}") + private String frontendUrl; + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, + AuthenticationException exception) throws IOException, ServletException { + + log.error("OAuth2 로그인 실패: {}", exception.getMessage()); + + // 프론트엔드 에러 페이지로 리다이렉트 + String redirectUrl = frontendUrl + "/oauth/error?message=" + exception.getMessage(); + + response.sendRedirect(redirectUrl); + } +} \ No newline at end of file diff --git a/src/main/java/com/back/global/security/CustomOAuth2LoginSuccessHandler.java b/src/main/java/com/back/global/security/CustomOAuth2LoginSuccessHandler.java new file mode 100644 index 00000000..107671a9 --- /dev/null +++ b/src/main/java/com/back/global/security/CustomOAuth2LoginSuccessHandler.java @@ -0,0 +1,43 @@ +package com.back.global.security; + +import com.back.domain.user.service.UserService; +import com.back.global.jwt.JwtUtil; +import com.back.global.rq.Rq; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +@Component +@RequiredArgsConstructor +public class CustomOAuth2LoginSuccessHandler implements AuthenticationSuccessHandler { + private final Rq rq; + private final JwtUtil jwtUtil; + private final UserService userService; + + @Value("${FRONTEND_URL}") + private String frontendUrl; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + SecurityUser securityUser = (SecurityUser) authentication.getPrincipal(); + + // Access Token 생성 + String accessToken = jwtUtil.generateAccessToken(securityUser.getId(), securityUser.getEmail()); + + // 쿠키에 토큰 저장 + rq.setCrossDomainCookie("accessToken", accessToken, (int) TimeUnit.MINUTES.toSeconds(20)); + + // 프론트엔드로 리다이렉트 + String redirectUrl = frontendUrl + "/oauth/success"; + + response.sendRedirect(redirectUrl); + } +} \ No newline at end of file diff --git a/src/main/java/com/back/global/security/CustomOAuth2UserService.java b/src/main/java/com/back/global/security/CustomOAuth2UserService.java new file mode 100644 index 00000000..3d35f4ce --- /dev/null +++ b/src/main/java/com/back/global/security/CustomOAuth2UserService.java @@ -0,0 +1,78 @@ +package com.back.global.security; + +import com.back.domain.user.entity.User; +import com.back.domain.user.service.UserService; +import com.back.global.rsData.RsData; +import lombok.RequiredArgsConstructor; +import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.security.oauth2.core.OAuth2AuthenticationException; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Map; + +@Service +@RequiredArgsConstructor +public class CustomOAuth2UserService extends DefaultOAuth2UserService { + private final UserService userService; + + // OAuth2 로그인 성공 시 자동 호출 + @Override + @Transactional + public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { + + OAuth2User oAuth2User = super.loadUser(userRequest); + + String oauthUserId = ""; + String providerTypeCode = userRequest.getClientRegistration().getRegistrationId().toUpperCase(); + String nickname = ""; + String email = ""; + + switch (providerTypeCode) { + case "KAKAO" -> { + Map attributes = oAuth2User.getAttributes(); + Map attributesProperties = (Map) attributes.get("properties"); + + oauthUserId = oAuth2User.getName(); + nickname = (String) attributesProperties.get("nickname"); + } + case "GOOGLE" -> { + oauthUserId = oAuth2User.getName(); + nickname = (String) oAuth2User.getAttributes().get("name"); + email = (String) oAuth2User.getAttributes().get("email"); + } + case "NAVER" -> { + Map attributes = oAuth2User.getAttributes(); + Map attributesProperties = (Map) attributes.get("response"); + + oauthUserId = (String) attributesProperties.get("id"); + nickname = (String) attributesProperties.get("nickname"); + email = (String) attributesProperties.get("email"); + } + } + + // OAuth ID를 제공자와 함께 저장 (예: kakao_123456789) + String uniqueOauthId = providerTypeCode.toLowerCase() + "_" + oauthUserId; + RsData rsData = userService.findOrCreateOAuthUser(uniqueOauthId, email, nickname); + + if (rsData.code()<200 || rsData.code()>299) { + throw new OAuth2AuthenticationException("사용자 생성/조회 실패: " + rsData.message()); + } + + User user = rsData.data(); + + String userEmail = user.getEmail() != null && !user.getEmail().trim().isEmpty() + ? user.getEmail() : "unknown"; + + // securityContext + return new SecurityUser( + user.getId(), + userEmail, + user.getNickname(), + user.getAuthorities(), + oAuth2User.getAttributes() + ); + } +} diff --git a/src/main/java/com/back/global/security/SecurityConfig.java b/src/main/java/com/back/global/security/SecurityConfig.java index d3063b10..dc469757 100644 --- a/src/main/java/com/back/global/security/SecurityConfig.java +++ b/src/main/java/com/back/global/security/SecurityConfig.java @@ -18,6 +18,21 @@ @EnableWebSecurity public class SecurityConfig { + private final CustomOAuth2UserService customOAuth2UserService; + private final CustomOAuth2LoginSuccessHandler oauth2SuccessHandler; + private final CustomOAuth2LoginFailureHandler oauth2FailureHandler; + private final CustomOAuth2AuthorizationRequestResolver customOAuth2AuthorizationRequestResolver; + + public SecurityConfig(CustomOAuth2UserService customOAuth2UserService, + CustomOAuth2LoginSuccessHandler oauth2SuccessHandler, + CustomOAuth2LoginFailureHandler oauth2FailureHandler, + CustomOAuth2AuthorizationRequestResolver customOAuth2AuthorizationRequestResolver) { + this.customOAuth2UserService = customOAuth2UserService; + this.oauth2SuccessHandler = oauth2SuccessHandler; + this.oauth2FailureHandler = oauth2FailureHandler; + this.customOAuth2AuthorizationRequestResolver = customOAuth2AuthorizationRequestResolver; + } + @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http @@ -25,19 +40,45 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .cors(cors -> cors.configurationSource(corsConfigurationSource())) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth - .requestMatchers("/","/api/**").permitAll() + .requestMatchers("/").permitAll() .requestMatchers("/h2-console/**").permitAll() .requestMatchers("/oauth2/**").permitAll() + .requestMatchers("/login/oauth2/**").permitAll() .requestMatchers("/swagger-ui/**", "/api-docs/**").permitAll() + .requestMatchers("/api/user/**").permitAll() + .requestMatchers("/api/cocktail/**").permitAll() + + + // 회원 or 인증된 사용자만 가능 + .requestMatchers("/api/admin/**").hasRole("ADMIN") +// .requestMatchers("/api/cocktail/detail~~").authenticated() + + //그 외에는 인증해야함 .anyRequest().authenticated() ) + .formLogin(AbstractHttpConfigurer::disable) + .httpBasic(AbstractHttpConfigurer::disable) .oauth2Login(oauth2 -> oauth2 .authorizationEndpoint(authorization -> authorization - .baseUri("/api/oauth2/authorization") + .authorizationRequestResolver(customOAuth2AuthorizationRequestResolver) ) - .redirectionEndpoint(redirection -> redirection - .baseUri("/api/login/oauth2/code/*") + .userInfoEndpoint(userInfo -> userInfo + .userService(customOAuth2UserService) ) + .successHandler(oauth2SuccessHandler) + .failureHandler(oauth2FailureHandler) + ) + .exceptionHandling(exceptionHandling -> exceptionHandling + .authenticationEntryPoint((request, response, authException) -> { + response.setContentType("application/json;charset=UTF-8"); + response.setStatus(401); + response.getWriter().write("{\"code\":401,\"message\":\"로그인 후 이용해주세요.\"}"); + }) + .accessDeniedHandler((request, response, accessDeniedException) -> { + response.setContentType("application/json;charset=UTF-8"); + response.setStatus(403); + response.getWriter().write("{\"code\":403,\"message\":\"권한이 없습니다.\"}"); + }) ) .headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::sameOrigin)); diff --git a/src/main/java/com/back/global/security/SecurityUser.java b/src/main/java/com/back/global/security/SecurityUser.java index b9e210f5..25aa02b6 100644 --- a/src/main/java/com/back/global/security/SecurityUser.java +++ b/src/main/java/com/back/global/security/SecurityUser.java @@ -18,21 +18,30 @@ public class SecurityUser extends User implements OAuth2User { @Getter private String email; + private Map attributes; + + // OAuth2 전용 생성자 (패스워드 없음) public SecurityUser( long id, String email, String name, - String password, - Collection authorities + Collection authorities, + Map attributes ) { - super(email, password , authorities); + super(email, "", authorities); // OAuth2에서는 빈 패스워드 this.id = id; this.name = name; this.email = email; + this.attributes = attributes; } @Override public Map getAttributes() { - return Map.of(); + return attributes; + } + + @Override + public String getName() { + return name; // OAuth2User 인터페이스용 } } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index a1d1a3f5..d8f8c3bf 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -22,6 +22,10 @@ spring: format_sql: true show_sql: true +# 개발 환경 URL 설정 +FRONTEND_URL: http://localhost:3000 +BASE_URL: http://localhost:8080 + # Swagger 설정 springdoc: api-docs: @@ -30,6 +34,19 @@ springdoc: path: /swagger-ui.html operationsSorter: method +# 개발용 상세 로깅 +logging: + level: + org.hibernate.orm.jdbc.bind: TRACE + org.hibernate.orm.jdbc.extract: TRACE + org.springframework.transaction.interceptor: TRACE + com.back: DEBUG + +# 쿠키 보안 설정 (HTTP 환경용) +custom: + cookie: + secure: false + # # AI 설정 # ai: # openai: diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 00000000..db3ab288 --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,44 @@ +# 프로덕션 환경 설정 +#spring: +# datasource: +# url: ${DATABASE_URL} +# +# +# jpa: +# hibernate: +# ddl-auto: update +# properties: +# hibernate: +# show_sql: false + + +springdoc: + swagger-ui: + enabled: false + +logging: + level: + com.back: INFO + root: WARN + +# 쿠키 보안 설정 +custom: + cookie: + secure: true + +# OAuth2 배포 환경 설정 +spring: + security: + oauth2: + client: + registration: + kakao: + redirect-uri: '${BASE_URL}/api/{action}/oauth2/code/{registrationId}' + google: + redirect-uri: '${BASE_URL}/api/{action}/oauth2/code/{registrationId}' + naver: + redirect-uri: '${BASE_URL}/api/{action}/oauth2/code/{registrationId}' + +# 프로덕션 환경 URL 설정 +BASE_URL: ${BASE_URL} +FRONTEND_URL: ${FRONTEND_URL} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 44fcb5e0..cfcc301e 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -2,6 +2,9 @@ spring: profiles: active: dev + config: + import: optional:file:.env[.properties] + security: oauth2: client: @@ -11,11 +14,11 @@ spring: scope: profile_nickname # 카카오 닉네임만 가져옴 client-name: Kakao authorization-grant-type: authorization_code - redirect-uri: '{baseUrl}/api/{action}/oauth2/code/{registrationId}' + redirect-uri: '${BASE_URL}/{action}/oauth2/code/{registrationId}' google: client-id: ${GOOGLE_OAUTH2_CLIENT_ID} client-secret: ${GOOGLE_OAUTH2_CLIENT_SECRET} - redirect-uri: '{baseUrl}/api/{action}/oauth2/code/{registrationId}' + redirect-uri: '${BASE_URL}/{action}/oauth2/code/{registrationId}' client-name: Google scope: profile naver: @@ -24,7 +27,7 @@ spring: scope: profile_nickname # 네이버 닉네임만 가져옴 client-name: Naver authorization-grant-type: authorization_code - redirect-uri: '{baseUrl}/api/{action}/oauth2/code/{registrationId}' + redirect-uri: '${BASE_URL}/{action}/oauth2/code/{registrationId}' provider: kakao: authorization-uri: https://kauth.kakao.com/oauth/authorize @@ -40,13 +43,6 @@ spring: springdoc: default-produces-media-type: application/json;charset=UTF-8 -logging: - level: - org.hibernate.orm.jdbc.bind: TRACE - org.hibernate.orm.jdbc.extract: TRACE - org.springframework.transaction.interceptor: TRACE - com.back: DEBUG - server: address: 0.0.0.0 port: 8080