From f9251609ee596bb2ed3516b7ae0d0b38d0908081 Mon Sep 17 00:00:00 2001 From: JaeSeo Yang <96044622+psychology50@users.noreply.github.com> Date: Sun, 31 Mar 2024 23:43:07 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20Swagger=20+=20Security=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#30)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * rename: 로그인 요청 dto @schema 추가 * chore: server domain 환경 설정 external-api -> infra * chore: server domain property bean 등록 * chore: application-infra server 블럭 수정 * fix: swagger server url 환경변수 경로 수정 * chore: cors 설정 추가 * refactor: cors 설정 파일 분리 * rename: jwt security config -> security adpater config * chore: bcryptpasswordencoder -> passwordencoder * fix: 동일한 클래스명의 DTO @Schema name 속성 설정 * refactor: 운영 환경 별 security filter chain 설정 분리 * chore: external api 모듈 내 jackson nullable module 종속성 추가 * refactor: security auth config 분리 * refactor: security config swagger endpoint 프로필 별 설정 분리 * feat: simple granted authority 역직렬화 이슈로 custom granted authority 클래스 선언 * chore: external-api 내 jackson config 설정 * fix: security user details 역직렬화 문제 해결 * fix: security config 개발 환경 옵션 수정 * fix: custom granted authority equals 수정 * chore: docker hub 경로 수정 --- .github/workflows/deploy.yml | 6 +- pennyway-app-external-api/build.gradle | 3 + .../pennyway/api/apis/auth/dto/SignInReq.java | 4 +- .../pennyway/api/apis/auth/dto/SignUpReq.java | 2 +- .../CustomGrantedAuthority.java | 48 ++++++++++ .../authentication/SecurityUserDetails.java | 26 +++--- .../co/pennyway/api/config/JacksonConfig.java | 20 +++++ .../co/pennyway/api/config/SwaggerConfig.java | 4 +- .../api/config/security/CorsConfig.java | 33 +++++++ ...Config.java => SecurityAdapterConfig.java} | 6 +- .../config/security/SecurityAuthConfig.java | 52 +++++++++++ .../api/config/security/SecurityConfig.java | 88 +++++++++---------- .../src/main/resources/application.yml | 5 -- .../common/properties/ServerProperties.java | 13 +++ .../config/ConfigurationPropertiesConfig.java | 12 +++ .../src/main/resources/application-infra.yml | 6 ++ 16 files changed, 254 insertions(+), 74 deletions(-) create mode 100644 pennyway-app-external-api/src/main/java/kr/co/pennyway/api/common/security/authentication/CustomGrantedAuthority.java create mode 100644 pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/JacksonConfig.java create mode 100644 pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/CorsConfig.java rename pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/{JwtSecurityConfig.java => SecurityAdapterConfig.java} (75%) create mode 100644 pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityAuthConfig.java create mode 100644 pennyway-infra/src/main/java/kr/co/pennyway/infra/common/properties/ServerProperties.java create mode 100644 pennyway-infra/src/main/java/kr/co/pennyway/infra/config/ConfigurationPropertiesConfig.java diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index afaf055b2..724c74584 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -55,8 +55,8 @@ jobs: - name: docker build and push run: | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} - docker build -t jinlee1703/pennyway-was . - docker push jinlee1703/pennyway-was + docker build -t pennyway/pennyway-was . + docker push pennyway/pennyway-was # 5. AWS SSM을 통한 Run-Command (Docker 이미지 pull 후 docker-compose를 통한 실행) - name: AWS SSM Send-Command @@ -71,5 +71,5 @@ jobs: command: | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} docker system prune -a -f - docker pull jinlee1703/pennyway-was + docker pull pennyway/pennyway-was docker-compose up -d \ No newline at end of file diff --git a/pennyway-app-external-api/build.gradle b/pennyway-app-external-api/build.gradle index dd868716b..2ae563a35 100644 --- a/pennyway-app-external-api/build.gradle +++ b/pennyway-app-external-api/build.gradle @@ -24,6 +24,9 @@ dependencies { /* Swagger */ implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.4.0' + /* jackson */ + implementation group: 'org.openapitools', name: 'jackson-databind-nullable', version: '0.2.6' + implementation 'org.springframework.boot:spring-boot-starter-web:3.2.3' implementation 'org.springframework.boot:spring-boot-starter-validation:3.2.3' } diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/auth/dto/SignInReq.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/auth/dto/SignInReq.java index 97cca37b8..64e4f4668 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/auth/dto/SignInReq.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/auth/dto/SignInReq.java @@ -2,11 +2,9 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -@NoArgsConstructor(access = AccessLevel.PRIVATE) public class SignInReq { + @Schema(name = "signInReqGeneral", title = "로그인 요청") public record General( @Schema(description = "아이디", example = "pennyway") @NotBlank(message = "아이디를 입력해주세요") diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/auth/dto/SignUpReq.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/auth/dto/SignUpReq.java index fe234eddf..2ce7ad446 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/auth/dto/SignUpReq.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/auth/dto/SignUpReq.java @@ -40,7 +40,7 @@ public String password() { } } - @Schema(title = "일반 회원가입 요청 DTO") + @Schema(name = "signUpReqGeneral", title = "일반 회원가입 요청 DTO") public record General( @Schema(description = "아이디", example = "pennyway") @NotBlank(message = "아이디를 입력해주세요") diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/common/security/authentication/CustomGrantedAuthority.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/common/security/authentication/CustomGrantedAuthority.java new file mode 100644 index 000000000..f6fc3848a --- /dev/null +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/common/security/authentication/CustomGrantedAuthority.java @@ -0,0 +1,48 @@ +package kr.co.pennyway.api.common.security.authentication; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.util.Assert; + +import java.io.Serial; +import java.io.Serializable; + +public final class CustomGrantedAuthority implements GrantedAuthority, Serializable { + @Serial + private static final long serialVersionUID = 1L; + + private final String role; + + @JsonCreator + public CustomGrantedAuthority(@JsonProperty("authority") String role) { + Assert.hasText(role, "role must not be empty"); + this.role = role; + } + + @Override + public String getAuthority() { + return role; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof CustomGrantedAuthority cga) { + return this.role.equals(cga.getAuthority()); + } + return false; + } + + @Override + public int hashCode() { + return this.role.hashCode(); + } + + @Override + public String toString() { + return this.role; + } +} diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/common/security/authentication/SecurityUserDetails.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/common/security/authentication/SecurityUserDetails.java index 250d9cfc7..f5dc6ac68 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/common/security/authentication/SecurityUserDetails.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/common/security/authentication/SecurityUserDetails.java @@ -2,21 +2,27 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import kr.co.pennyway.domain.domains.user.domain.User; -import kr.co.pennyway.domain.domains.user.type.Role; +import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; -import java.util.Arrays; +import java.io.Serial; import java.util.Collection; +import java.util.List; @Getter -public class SecurityUserDetails implements UserDetails { - private final Long userId; - private final String username; - private final Collection authorities; - private final boolean accountNonLocked; +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class SecurityUserDetails implements UserDetails { + @Serial + private static final long serialVersionUID = 1L; + + private Long userId; + private String username; + private Collection authorities; + private boolean accountNonLocked; @JsonIgnore private boolean enabled; @@ -39,10 +45,7 @@ public static UserDetails from(User user) { return SecurityUserDetails.builder() .userId(user.getId()) .username(user.getUsername()) - .authorities(Arrays.stream(Role.values()) - .filter(roleType -> roleType == user.getRole()) - .map(roleType -> (GrantedAuthority) roleType::getType) - .toList()) + .authorities(List.of(new CustomGrantedAuthority(user.getRole().getType()))) .accountNonLocked(user.getLocked()) .build(); } @@ -91,4 +94,5 @@ public String toString() { ", accountNonLocked=" + accountNonLocked + '}'; } + } diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/JacksonConfig.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/JacksonConfig.java new file mode 100644 index 000000000..d2d1e035b --- /dev/null +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/JacksonConfig.java @@ -0,0 +1,20 @@ +package kr.co.pennyway.api.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.RequiredArgsConstructor; +import org.openapitools.jackson.nullable.JsonNullableModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +@Configuration +@RequiredArgsConstructor +public class JacksonConfig { + @Bean + Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() { + return new Jackson2ObjectMapperBuilder() + .serializationInclusion(JsonInclude.Include.ALWAYS) + .modulesToInstall(new JsonNullableModule()) + .indentOutput(true); + } +} diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/SwaggerConfig.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/SwaggerConfig.java index ab6515cd3..174c3bcbf 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/SwaggerConfig.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/SwaggerConfig.java @@ -17,8 +17,8 @@ @Configuration @OpenAPIDefinition( servers = { - @Server(url = "${pennyway.domain.local}", description = "Local Server"), - @Server(url = "${pennyway.domain.dev}", description = "Develop Server") + @Server(url = "${pennyway.server.domain.local}", description = "Local Server"), + @Server(url = "${pennyway.server.domain.dev}", description = "Develop Server") } ) @RequiredArgsConstructor diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/CorsConfig.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/CorsConfig.java new file mode 100644 index 000000000..e0aaf5925 --- /dev/null +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/CorsConfig.java @@ -0,0 +1,33 @@ +package kr.co.pennyway.api.config.security; + +import kr.co.pennyway.infra.common.properties.ServerProperties; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpHeaders; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import java.util.List; + +@Configuration +@RequiredArgsConstructor +public class CorsConfig { + private final ServerProperties serverProperties; + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration configuration = new CorsConfiguration(); + configuration.setAllowedOrigins(List.of(serverProperties.getLocal(), serverProperties.getDev())); + configuration.setAllowedMethods(List.of("GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE")); + configuration.setAllowedHeaders(List.of("*")); + configuration.setExposedHeaders(List.of(HttpHeaders.AUTHORIZATION, HttpHeaders.SET_COOKIE)); + configuration.setMaxAge(3600L); + configuration.setAllowCredentials(true); + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", configuration); + return source; + } +} diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/JwtSecurityConfig.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityAdapterConfig.java similarity index 75% rename from pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/JwtSecurityConfig.java rename to pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityAdapterConfig.java index 70133bf1f..93bed2abf 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/JwtSecurityConfig.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityAdapterConfig.java @@ -4,6 +4,7 @@ import kr.co.pennyway.api.common.security.filter.JwtExceptionFilter; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.SecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.DefaultSecurityFilterChain; @@ -11,12 +12,15 @@ @Configuration @RequiredArgsConstructor -public class JwtSecurityConfig extends SecurityConfigurerAdapter { +public class SecurityAdapterConfig extends SecurityConfigurerAdapter { + private final DaoAuthenticationProvider daoAuthenticationProvider; + private final JwtExceptionFilter jwtExceptionFilter; private final JwtAuthenticationFilter jwtAuthenticationFilter; @Override public void configure(HttpSecurity http) throws Exception { + http.authenticationProvider(daoAuthenticationProvider); http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); http.addFilterBefore(jwtExceptionFilter, JwtAuthenticationFilter.class); } diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityAuthConfig.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityAuthConfig.java new file mode 100644 index 000000000..367dc6090 --- /dev/null +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityAuthConfig.java @@ -0,0 +1,52 @@ +package kr.co.pennyway.api.config.security; + +import com.fasterxml.jackson.databind.ObjectMapper; +import kr.co.pennyway.api.common.security.authentication.UserDetailServiceImpl; +import kr.co.pennyway.api.common.security.handler.JwtAccessDeniedHandler; +import kr.co.pennyway.api.common.security.handler.JwtAuthenticationEntryPoint; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.access.AccessDeniedHandler; + +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) +@Configuration +public class SecurityAuthConfig { + private final UserDetailServiceImpl userDetailsService; + private final ObjectMapper objectMapper; + + @Bean + public PasswordEncoder bCryptPasswordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public AccessDeniedHandler accessDeniedHandler() { + return new JwtAccessDeniedHandler(objectMapper); + } + + @Bean + public AuthenticationEntryPoint authenticationEntryPoint() { + return new JwtAuthenticationEntryPoint(objectMapper); + } + + @Bean + public DaoAuthenticationProvider daoAuthenticationProvider() { + DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); + daoAuthenticationProvider.setUserDetailsService(userDetailsService); + daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder()); + return daoAuthenticationProvider; + } + + @Bean + public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { + return config.getAuthenticationManager(); + } +} diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityConfig.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityConfig.java index c1ae423d3..024f787cc 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityConfig.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityConfig.java @@ -1,94 +1,86 @@ package kr.co.pennyway.api.config.security; -import com.fasterxml.jackson.databind.ObjectMapper; -import kr.co.pennyway.api.common.security.handler.JwtAccessDeniedHandler; -import kr.co.pennyway.api.common.security.handler.JwtAuthenticationEntryPoint; import lombok.RequiredArgsConstructor; import org.springframework.boot.autoconfigure.security.ConditionalOnDefaultWebSecurity; import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.autoconfigure.security.servlet.PathRequest; 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.config.Customizer; +import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry; 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.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.AccessDeniedHandler; -import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; - -import java.util.Arrays; @Configuration @EnableWebSecurity @ConditionalOnDefaultWebSecurity @RequiredArgsConstructor public class SecurityConfig { - private static final String[] publicReadOnlyPublicEndpoints = { + private static final String[] READ_ONLY_PUBLIC_ENDPOINTS = { "/favicon.ico", // Swagger "/api-docs/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger", }; - private final ObjectMapper objectMapper; - private final JwtSecurityConfig jwtSecurityConfig; + private static final String[] ANONYMOUS_ENDPOINTS = {"/v1/auth/**"}; - @Bean - public BCryptPasswordEncoder bCryptPasswordEncoder() { - return new BCryptPasswordEncoder(); - } + private final SecurityAdapterConfig securityAdapterConfig; + private final CorsConfigurationSource corsConfigurationSource; + private final AccessDeniedHandler accessDeniedHandler; + private final AuthenticationEntryPoint authenticationEntryPoint; @Bean - public AccessDeniedHandler accessDeniedHandler() { - return new JwtAccessDeniedHandler(objectMapper); + @Profile({"local", "dev", "test"}) + @Order(SecurityProperties.BASIC_AUTH_ORDER) + public SecurityFilterChain filterChainDev(HttpSecurity http) throws Exception { + return defaultSecurity(http) + .cors((cors) -> cors.configurationSource(corsConfigurationSource)) + .authorizeHttpRequests( + auth -> defaultAuthorizeHttpRequests(auth) + .requestMatchers(READ_ONLY_PUBLIC_ENDPOINTS).permitAll() + .anyRequest().authenticated() + ).build(); } @Bean - public AuthenticationEntryPoint authenticationEntryPoint() { - return new JwtAuthenticationEntryPoint(objectMapper); + @Profile({"prod"}) + @Order(SecurityProperties.BASIC_AUTH_ORDER) + public SecurityFilterChain filterChainProd(HttpSecurity http) throws Exception { + return defaultSecurity(http) + .cors(AbstractHttpConfigurer::disable) + .authorizeHttpRequests( + auth -> defaultAuthorizeHttpRequests(auth).anyRequest().authenticated() + ).build(); } - @Bean - @Order(SecurityProperties.BASIC_AUTH_ORDER) - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { - http.csrf(AbstractHttpConfigurer::disable) - .httpBasic(AbstractHttpConfigurer::disable) - .cors((cors) -> cors.configurationSource(corsConfigurationSource())) - .formLogin(AbstractHttpConfigurer::disable) - .logout(AbstractHttpConfigurer::disable) + private HttpSecurity defaultSecurity(HttpSecurity http) throws Exception { + return http.httpBasic(AbstractHttpConfigurer::disable) + .csrf(AbstractHttpConfigurer::disable) .sessionManagement((sessionManagement) -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .with(jwtSecurityConfig, Customizer.withDefaults()) - .authorizeHttpRequests( - auth -> auth.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() - .requestMatchers(HttpMethod.OPTIONS, "*").permitAll() - .requestMatchers(HttpMethod.GET, publicReadOnlyPublicEndpoints).permitAll() - .anyRequest().permitAll() - ) + .formLogin(AbstractHttpConfigurer::disable) + .logout(AbstractHttpConfigurer::disable) + .with(securityAdapterConfig, Customizer.withDefaults()) .exceptionHandling( exception -> exception - .accessDeniedHandler(accessDeniedHandler()) - .authenticationEntryPoint(authenticationEntryPoint()) + .accessDeniedHandler(accessDeniedHandler) + .authenticationEntryPoint(authenticationEntryPoint) ); - - return http.build(); } - // TODO: dev, test, prod 환경이 정해지면 수정 필요. - @Bean - CorsConfigurationSource corsConfigurationSource() { - CorsConfiguration configuration = new CorsConfiguration(); - configuration.addAllowedOrigin("http://localhost:3000"); - configuration.setAllowedMethods(Arrays.asList("GET", "POST", "OPTIONS", "PUT", "PATCH", "DELETE")); - configuration.setAllowCredentials(true); - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - source.registerCorsConfiguration("/**", configuration); - return source; + private AbstractRequestMatcherRegistry.AuthorizedUrl> defaultAuthorizeHttpRequests( + AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry auth) { + return auth.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() + .requestMatchers(HttpMethod.OPTIONS, "*").permitAll() + .requestMatchers(ANONYMOUS_ENDPOINTS).anonymous(); } } diff --git a/pennyway-app-external-api/src/main/resources/application.yml b/pennyway-app-external-api/src/main/resources/application.yml index d13f5062a..2d360b542 100644 --- a/pennyway-app-external-api/src/main/resources/application.yml +++ b/pennyway-app-external-api/src/main/resources/application.yml @@ -4,11 +4,6 @@ spring: local: common, domain, infra dev: common, domain, infra -pennyway: - domain: - local: ${PENNYWAY_DOMAIN_LOCAL} - dev: ${PENNYWAY_DOMAIN_DEV} - jwt: secret-key: access-token: ${JWT_ACCESS_SECRET_KEY} diff --git a/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/properties/ServerProperties.java b/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/properties/ServerProperties.java new file mode 100644 index 000000000..10fb35942 --- /dev/null +++ b/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/properties/ServerProperties.java @@ -0,0 +1,13 @@ +package kr.co.pennyway.infra.common.properties; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Getter +@RequiredArgsConstructor +@ConfigurationProperties(prefix = "pennyway.server.domain") +public class ServerProperties { + private final String local; + private final String dev; +} diff --git a/pennyway-infra/src/main/java/kr/co/pennyway/infra/config/ConfigurationPropertiesConfig.java b/pennyway-infra/src/main/java/kr/co/pennyway/infra/config/ConfigurationPropertiesConfig.java new file mode 100644 index 000000000..63c859194 --- /dev/null +++ b/pennyway-infra/src/main/java/kr/co/pennyway/infra/config/ConfigurationPropertiesConfig.java @@ -0,0 +1,12 @@ +package kr.co.pennyway.infra.config; + +import kr.co.pennyway.infra.common.properties.ServerProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@EnableConfigurationProperties({ + ServerProperties.class +}) +@Configuration +public class ConfigurationPropertiesConfig { +} diff --git a/pennyway-infra/src/main/resources/application-infra.yml b/pennyway-infra/src/main/resources/application-infra.yml index ee08bd17e..f9c75be13 100644 --- a/pennyway-infra/src/main/resources/application-infra.yml +++ b/pennyway-infra/src/main/resources/application-infra.yml @@ -4,6 +4,12 @@ spring: local: common dev: common +pennyway: + server: + domain: + local: ${PENNYWAY_DOMAIN_LOCAL} + dev: ${PENNYWAY_DOMAIN_DEV} + --- spring: config: