Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 0 additions & 36 deletions src/main/java/com/pinHouse/server/core/config/SwaggerConfig.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.pinHouse.server.core.config.swaagger;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springdoc.core.customizers.OpenApiCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import java.util.Map;
import java.util.TreeMap;

@Profile("local")
@Configuration
public class LocalSwaggerConfig {

@Bean
public OpenAPI openAPI() {
String jwt = "JWT";
SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwt);
Components components = new Components().addSecuritySchemes(jwt, new SecurityScheme()
.name(jwt)
.type(SecurityScheme.Type.HTTP)
.scheme("Bearer")
.bearerFormat("JWT")
);
return new OpenAPI()
.components(components)
.info(apiInfo())
.addSecurityItem(securityRequirement);
}

private Info apiInfo() {
return new Info()
.title("PinHouse Swagger")
.description("핀하우스 로컬 스웨거입니다.")
.version("1.0.0");
}

/// 필요없는 스키마 제거
@Bean
public OpenApiCustomizer removeGenericSchemas() {
return openApi -> {
openApi.getComponents().getSchemas().keySet().removeIf(name ->
name.contains("ApiResponse") || name.contains("SliceResponse")
);
};
}

/// 스키마 이름 기준 오름차순
@Bean
public OpenApiCustomizer sortSchemasAlphabetically() {
return openApi -> {
Map<String, Schema> schemas = openApi.getComponents().getSchemas();
openApi.getComponents().setSchemas(new TreeMap<>(schemas));
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.pinHouse.server.core.config.swaagger;

import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.servers.Server;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springdoc.core.customizers.OpenApiCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import java.util.Map;
import java.util.TreeMap;

/**
* Swagger / OpenAPI 설정 클래스
* - HTTPS 설정으로 인해 @OpenAPIDefinition 추가
* - 스웨거 내부 JWT 설정 추가
*/

@Configuration
@Profile("dev")
@OpenAPIDefinition(servers = {@Server(url = "https://api.pinhouse.cloud", description = "PinHouse 개발 서버")})
public class SwaggerConfig {

@Bean
public OpenAPI openAPI() {
String jwt = "JWT";
SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwt);
Components components = new Components().addSecuritySchemes(jwt, new SecurityScheme()
.name(jwt)
.type(SecurityScheme.Type.HTTP)
.scheme("Bearer")
.bearerFormat("JWT")
);
return new OpenAPI()
.components(components)
.info(apiInfo())
.addSecurityItem(securityRequirement);
}

private Info apiInfo() {
return new Info()
.title("PinHouse Swagger")
.description("핀하우스 스웨거입니다.")
.version("1.0.0");
}

@Bean
public OpenApiCustomizer removeGenericSchemas() {
return openApi -> {
openApi.getComponents().getSchemas().keySet().removeIf(name ->
name.contains("ApiResponse") || name.contains("SliceResponse")
);
};
}
/// 스키마 이름 기준 오름차순

@Bean
public OpenApiCustomizer sortSchemasAlphabetically() {
return openApi -> {
Map<String, Schema> schemas = openApi.getComponents().getSchemas();
openApi.getComponents().setSchemas(new TreeMap<>(schemas));
};
}
}
45 changes: 45 additions & 0 deletions src/main/java/com/pinHouse/server/security/config/CorsConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.pinHouse.server.security.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
public class CorsConfig {

@Value("${cors.front.local}")
private String front_local;

@Value("${cors.front.dev}")
private String front_dev;

@Value("${cors.back.dev}")
private String back_dev;

/**
* CORS 설정을 진행합니다.
*/
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();

/// CORS 추가
configuration.addAllowedOriginPattern(front_local);
configuration.addAllowedOriginPattern(front_dev);
configuration.addAllowedOriginPattern(back_dev);

configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
configuration.setAllowCredentials(true);

configuration.addExposedHeader("Authorization");

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.pinHouse.server.security.jwt.filter;
package com.pinHouse.server.security.config;

import com.pinHouse.server.platform.domain.user.Role;
import io.micrometer.common.lang.Nullable;
Expand Down Expand Up @@ -38,9 +38,9 @@ public class RequestMatcherHolder {
new RequestInfo(GET, "/docs/**", null),
new RequestInfo(GET, "/*.ico", null),
new RequestInfo(GET, "/resources/**", null),
new RequestInfo(GET, "/style.css", null),
new RequestInfo(GET, "/index.html", null),
new RequestInfo(GET, "/error", null),
new RequestInfo(GET, "/kikihi.png", null),

// Swagger UI 및 API 문서 관련 요청
new RequestInfo(GET, "/v3/api-docs/**", null),
Expand All @@ -51,10 +51,7 @@ public class RequestMatcherHolder {

// 정적 아이콘 요청
new RequestInfo(GET, "/favicon.ico", null),
new RequestInfo(GET, "/apple-touch-icon.png", null),

// 검색 (임시로 개방)
new RequestInfo(GET, "/api/v1/search", null)
new RequestInfo(GET, "/apple-touch-icon.png", null)

);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.pinHouse.server.security.config;

import com.pinHouse.server.security.jwt.filter.JwtAuthenticationDeniedHandler;
import com.pinHouse.server.security.jwt.filter.JwtAuthenticationFailureHandler;
import com.pinHouse.server.security.jwt.filter.JwtAuthenticationFilter;
import com.pinHouse.server.security.oauth2.handler.OAuth2SuccessHandler;
import com.pinHouse.server.security.oauth2.service.OAuth2UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfigurationSource;

import static com.pinHouse.server.platform.domain.user.Role.ADMIN;
import static com.pinHouse.server.platform.domain.user.Role.USER;

/**
* Spring Security 설정 클래스
*
* 애플리케이션의 인증 및 권한 부여 정책을 정의한다.
*/

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final OAuth2UserService oAuth2UserService;
private final OAuth2SuccessHandler oAuth2SuccessHandler;
private final JwtAuthenticationFilter jwtFilter;
private final JwtAuthenticationFailureHandler jwtFailureHandler;
private final JwtAuthenticationDeniedHandler jwtDeniedHandler;
private final RequestMatcherHolder requestMatcherHolder;
private final CorsConfigurationSource corsConfigurationSource;


@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.cors(cors -> cors.configurationSource(corsConfigurationSource))
.formLogin(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers(requestMatcherHolder.getRequestMatchersByMinRole(null))
.permitAll()
.requestMatchers(requestMatcherHolder.getRequestMatchersByMinRole(USER))
.hasAnyAuthority(ADMIN.getRole(), USER.getRole())
.requestMatchers(requestMatcherHolder.getRequestMatchersByMinRole(ADMIN))
.hasAnyAuthority(ADMIN.getRole())
.anyRequest().authenticated()
)
.oauth2Login(oauth2 -> oauth2
.userInfoEndpoint(userInfo -> userInfo
.userService(oAuth2UserService)
)
.successHandler(oAuth2SuccessHandler)
.failureHandler((request, response, exception) -> {
response.sendRedirect("/login?error");
})
)
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(exception -> {
exception.authenticationEntryPoint(jwtFailureHandler)
.accessDeniedHandler(jwtDeniedHandler);
});


return http.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.pinHouse.server.security.jwt.filter;

import com.pinHouse.server.core.response.response.ErrorCode;
import com.pinHouse.server.security.config.RequestMatcherHolder;
import com.pinHouse.server.security.jwt.exception.JwtAuthenticationException;
import com.pinHouse.server.security.jwt.util.JwtTokenExtractor;
import jakarta.servlet.FilterChain;
Expand Down Expand Up @@ -106,11 +107,6 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {

/// 상품 조회는 회원/비회원 구분해야되기에 모두 필터를 타도록 설정
if (request.getRequestURI().startsWith("/api/v1/products")) {
return false;
}

/// null 인 것 해결
return requestMatcherHolder.getRequestMatchersByMinRole(null)
.matches(request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class OAuth2SuccessHandler extends SimpleUrlAuthenticationSuccessHandler

private final JwtTokenUseCase tokenService;

@Value("${spring.front.host}")
@Value("${cors.front.dev}")
public String REDIRECT_PATH;

/*
Expand Down
Loading
Loading