- CORS 적용
[Customer]
- Customer No 사용 (MIS 용)
This commit is contained in:
Hyojin Ahn 2025-11-25 08:42:26 -05:00
parent 432155a8bc
commit 026da5fdcf
4 changed files with 107 additions and 25 deletions

View File

@ -1,6 +1,9 @@
package com.goi.erp.config; package com.goi.erp.config;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
@ -8,6 +11,10 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration @Configuration
@EnableMethodSecurity // @PreAuthorize 사용 가능 @EnableMethodSecurity // @PreAuthorize 사용 가능
@ -18,25 +25,35 @@ public class SecurityConfig {
@Bean @Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http http
// CSRF 비활성화 (API 서버라면 stateless) .csrf(csrf -> csrf.disable()) // CSRF 비활성화 (API 서버라면 stateless)
.csrf(csrf -> csrf.disable()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 세션 사용 안함
// 세션 사용 안함
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
// 요청 권한 설정
.authorizeHttpRequests(auth -> auth .authorizeHttpRequests(auth -> auth
.requestMatchers( .requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
"/swagger-ui/**", .anyRequest().authenticated()
"/v3/api-docs/**" ) // 요청 권한 설정
).permitAll() // 인증 없이 접근 허용 .addFilterBefore(new CorsFilter(corsConfigurationSource()), UsernamePasswordAuthenticationFilter.class) // JWT 필터 전에 CorsFilter 등록
.anyRequest().authenticated() // 나머지는 JWT 인증 필요 .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class); // JWT 필터
)
// JWT 필터 등록
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return http.build(); return http.build();
} }
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList(
"http://192.168.2.172:8000",
"http://localhost:8000",
"http://127.0.0.1:8000",
"https://homotypical-bowen-unlanguid.ngrok-free.dev"
));
configuration.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE","OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("Authorization","Content-Type"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
} }

View File

@ -99,7 +99,7 @@ public class CustomerController {
} }
// UPDATE // UPDATE
@PutMapping("/{uuid}") @PatchMapping("/{uuid}")
public ResponseEntity<CustomerResponseDto> updateCustomer( public ResponseEntity<CustomerResponseDto> updateCustomer(
@PathVariable UUID uuid, @PathVariable UUID uuid,
@RequestBody CustomerRequestDto requestDto) { @RequestBody CustomerRequestDto requestDto) {
@ -136,4 +136,44 @@ public class CustomerController {
customerService.deleteCustomer(uuid); customerService.deleteCustomer(uuid);
return ResponseEntity.noContent().build(); return ResponseEntity.noContent().build();
} }
// from MIS
@GetMapping("/{cusNo}")
public ResponseEntity<CustomerResponseDto> getCustomer(@PathVariable String cusNo) {
// 권한 체크
PermissionAuthenticationToken auth = (PermissionAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
if (auth == null || auth.getPermissionSet() == null) {
throw new AccessDeniedException("Permission information is missing");
}
PermissionSet permissionSet = auth.getPermissionSet();
if (!PermissionChecker.canDeleteCRM(permissionSet)) {
throw new AccessDeniedException("You do not have permission to read all CRM data");
}
//
CustomerResponseDto customer = customerService.getCustomerByNo(cusNo);
return ResponseEntity.ok(customer);
}
@PutMapping("/{cusNo}")
public ResponseEntity<CustomerResponseDto> updateCustomer(@PathVariable String cusNo,
@RequestBody CustomerRequestDto dto) {
// 권한 체크
PermissionAuthenticationToken auth = (PermissionAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
if (auth == null || auth.getPermissionSet() == null) {
throw new AccessDeniedException("Permission information is missing");
}
PermissionSet permissionSet = auth.getPermissionSet();
if (!PermissionChecker.canDeleteCRM(permissionSet)) {
throw new AccessDeniedException("You do not have permission to read all CRM data");
}
//
CustomerResponseDto updated = customerService.updateCustomerByNo(cusNo, dto);
return ResponseEntity.ok(updated);
}
} }

View File

@ -31,4 +31,8 @@ public interface CustomerRepository extends JpaRepository<Customer, Long> {
Page<CustomerResponseDto> findAllCustomerDtos(Pageable pageable); Page<CustomerResponseDto> findAllCustomerDtos(Pageable pageable);
Optional<Customer> findByCusUuid(UUID cusUuid); Optional<Customer> findByCusUuid(UUID cusUuid);
// from MIS
Optional<Customer> findByCusNo(String cusNo);
boolean existsByCusNo(String cusNo);
} }

View File

@ -48,13 +48,12 @@ public class CustomerService {
Customer customer = customerRepository.findByCusUuid(uuid) Customer customer = customerRepository.findByCusUuid(uuid)
.orElseThrow(() -> new RuntimeException("Customer not found")); .orElseThrow(() -> new RuntimeException("Customer not found"));
customer.setCusName(dto.getCusName()); if (dto.getCusName() != null) customer.setCusName(dto.getCusName());
customer.setCusNo(dto.getCusNo()); if (dto.getCusStatus() != null) customer.setCusStatus(dto.getCusStatus());
customer.setCusStatus(dto.getCusStatus()); if (dto.getCusAddress1() != null) customer.setCusAddress1(dto.getCusAddress1());
customer.setCusAddress1(dto.getCusAddress1()); if (dto.getCusAddress2() != null) customer.setCusAddress2(dto.getCusAddress2());
customer.setCusAddress2(dto.getCusAddress2()); if (dto.getCusCity() != null) customer.setCusCity(dto.getCusCity());
customer.setCusCity(dto.getCusCity()); if (dto.getCusProvince() != null) customer.setCusProvince(dto.getCusProvince());
customer.setCusProvince(dto.getCusProvince());
customerRepository.save(customer); customerRepository.save(customer);
return mapToDto(customer); return mapToDto(customer);
@ -74,4 +73,26 @@ public class CustomerService {
.cusStatus(customer.getCusStatus()) .cusStatus(customer.getCusStatus())
.build(); .build();
} }
// from MIS
public CustomerResponseDto getCustomerByNo(String cusNo) {
Customer customer = customerRepository.findByCusNo(cusNo)
.orElseThrow(() -> new RuntimeException("Customer not found"));
return mapToDto(customer);
}
public CustomerResponseDto updateCustomerByNo(String cusNo, CustomerRequestDto dto) {
Customer customer = customerRepository.findByCusNo(cusNo)
.orElseThrow(() -> new RuntimeException("Customer not found"));
customer.setCusName(dto.getCusName());
customer.setCusStatus(dto.getCusStatus());
customer.setCusAddress1(dto.getCusAddress1());
customer.setCusAddress2(dto.getCusAddress2());
customer.setCusCity(dto.getCusCity());
customer.setCusProvince(dto.getCusProvince());
customerRepository.save(customer);
return mapToDto(customer);
}
} }