通过Spring Cloud Gateway转发POST请求时出现403 CORS错误,直接请求BFF微服务正常的问题求助
通过Spring Cloud Gateway转发POST请求时出现403 CORS错误,直接请求BFF微服务正常的问题求助
大家好,我现在正在用React + Spring Boot搭建一个微服务应用,系统里包含API网关、BFF层还有其他业务服务。最近碰到一个棘手的问题:当我通过网关转发POST请求到BFF时,总是返回403错误,但直接调用BFF的接口却完全正常。折腾了好一阵还是没找到原因,麻烦各位帮忙排查一下!
网关的application.properties配置
eureka.client.service-url.defaultZone=http://eureka:password@localhost:8761/eureka spring.application.name=api-gateway spring.main.web-application-type=reactive logging.level.root=INFO logging.level.org.springframework.cloud.gateway.route.RouteDefinitionLocator=INFO logging.level.org.springframework.cloud.gateway=TRACE spring.cloud.gateway.discovery.locator.enabled=true spring.cloud.gateway.discovery.locator.lower-case-service-id=true ## BFF Service Route spring.cloud.gateway.routes[0].id=bff spring.cloud.gateway.routes[0].uri=http://localhost:8085 spring.cloud.gateway.routes[0].predicates[0]=Path=/** spring.cloud.gateway.routes[0].predicates[1]=Method=GET,POST,DELETE, OPTIONS ## Order Service Route spring.cloud.gateway.routes[1].id=order spring.cloud.gateway.routes[1].uri=lb://order spring.cloud.gateway.routes[1].predicates[0]=Path=/** ## Discovery Server Route spring.cloud.gateway.routes[2].id=discovery-service spring.cloud.gateway.routes[2].uri=http://localhost:8761 spring.cloud.gateway.routes[2].predicates[0]=Path=/eureka/web spring.cloud.gateway.routes[2].filters[0]=SetPath=/ ##Discovery Server Static Resources Route spring.cloud.gateway.routes[3].id=discovery-service-static spring.cloud.gateway.routes[3].uri=http://localhost:8761 spring.cloud.gateway.routes[3].predicates[0]=Path=/eureka/** spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8181/realms/spring-boot-microsevices-realm
网关的CorsConfig配置类
package com.mealkit.gateway.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class CorsConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // All endpoints in the application .allowedOrigins("http://localhost:3000") // Or other origins .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS") .allowedHeaders("*")// Or other HTTP methods .allowCredentials(true); } }; }}
BFF的Product控制器代码(直接请求此处接口正常)
package com.mealkit.bff.web.product; import com.mealkit.bff.api.model.product.request.ProductApiInput; import com.mealkit.bff.api.model.product.response.ProductApiOutput; import com.mealkit.bff.api.service.product.product.ProductService; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequiredArgsConstructor @RequestMapping("/api/product") @CrossOrigin(value = "http://localhost:3000") public class ProductWebApi { private final ProductService productService; @GetMapping("/getProductById/{productId}") public ResponseEntity<ProductApiOutput> getProductById(@PathVariable Long productId) throws Exception { return productService.getProductById(productId); } @PostMapping(value = "/getProductsById") public ResponseEntity<List<ProductApiOutput>> getProductsById(@RequestBody List<Long> productIdList) { return productService.getProductsById(productIdList); } @PostMapping("/getProductsByTag") public ResponseEntity<List<ProductApiOutput>> getProductByTag(@RequestBody List<Long> tagIdList) { return productService.getProductByTag(tagIdList); } @DeleteMapping("/deleteProduct/{productId}") public ResponseEntity<Void> deleteProduct(@PathVariable Long productId) { productService.deleteProduct(productId); return new ResponseEntity<>(HttpStatus.OK); } @PutMapping("/updateProduct") public ResponseEntity<Void> updateProduct(@RequestBody ProductApiInput productApiInput) { productService.updateProduct(productApiInput); return new ResponseEntity<>(HttpStatus.OK); } @PostMapping("/createProduct") public ResponseEntity<Void> createProduct(@RequestBody ProductApiInput productApiInput) { productService.createProduct(productApiInput); return new ResponseEntity<>(HttpStatus.OK); } }
前端请求代码
const URL = "http://localhost:"; const PORT = "8080"; const ORDER_PORT = "8080"; const ORDER_ENDPOINT = "/api/v1/order"; const PRODUCT_ENDPOINT = "/api/product"; const TAG_ENDPOINT = "/api/tag"; const BUSINESS_ENDPOINT = "/api/business"; export const getProductById = async (productId) => { try { const response = await fetch( `${URL}${PORT}${PRODUCT_ENDPOINT}/getProductById/${productId}` ); const data = await response.json(); return data; } catch (error) { console.error("Error:", error); throw error; } }; export const getProductsByTag = async (tags) => { try { const response = await fetch( `${URL}${PORT}${PRODUCT_ENDPOINT}/getProductsByTag`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(tags), } ); const data = await response.json(); return data; } catch (error) { console.error("Error:", error); throw error; } }; export const getProductsById = async (productIdList) => { try { const response = await fetch( `${URL}${PORT}${PRODUCT_ENDPOINT}/getProductsById`, { method: "POST", headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(productIdList), } ); const data = await response.json(); return data; } catch (error) { console.error("Error:", error); throw error; } }; export const getTagsByIds = async (tagIdList) => { try { const response = await fetch(`${TAG_ENDPOINT}/getTagsByIds`, { method: "POST", headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(tagIdList), }); const data = await response.json(); return data; } catch (error) { console.error("Error:", error); throw error; } }; export const getTagById = async (tagId) => { try { const response = await fetch( `${TAG_ENDPOINT}/getTagById/${tagId}` ); const data = await response.json(); return data; } catch (error) { console.error("Error:", error); throw error; } }; export const getTags = async () => { try { const response = await fetch(`${URL}${PORT}${TAG_ENDPOINT}/getTags`); const data = await response.json(); return data; } catch (error) { console.error("Error:", error); throw error; } }; export const businessGetProductById = async (productId) => { try { const response = await fetch( `${URL}${PORT}${BUSINESS_ENDPOINT}/getProductById/${productId}` ); const data = await response.json(); return data; } catch (error) { console.error("Error:", error); throw error; } }; export const placeOrder = async (products) => { try { const response = await fetch( `${URL}${ORDER_PORT}${ORDER_ENDPOINT}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(products), } ); const data = await response.json(); return data; } catch (error) { console.error("Error:", error); throw error; } };
备注:内容来源于stack exchange,提问作者Yekta Yüksel
相关产品推荐
相关产品推荐

