带网关的 CORS
CORS with gateway
我必须使用 spring-boot 创建一些微服务。创建了只有一个控制器并配置了 CORS 的 MailService:
package com.smdev.mailservice.controller;
import com.smdev.mailservice.model.dto.EmailAddress;
import com.smdev.mailservice.model.dto.SendMailDTO;
import com.smdev.mailservice.service.MailService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@Api
@RestController
@RequestMapping("/api/mail")
@CrossOrigin(origins = "*", methods = {RequestMethod.POST, RequestMethod.OPTIONS})
public class MailSendController {
private final MailService mailService;
@Autowired
public MailSendController(MailService mailService) {
this.mailService = mailService;
}
@ApiOperation(value = "Send message from 'Contact Us' form")
@ApiResponses({
@ApiResponse(code = 200, message = "E-Mail send successfully"),
@ApiResponse(code = 400, message = "Invalid data sent", response = ResponseEntity.class)
})
@PostMapping(value = "/feedback", consumes = {MediaType.APPLICATION_JSON_VALUE})
public void feedback(@Valid @RequestBody SendMailDTO sendMailDTO){
mailService.sendMessage(sendMailDTO, EmailAddress.FEEDBACK);
}
}
这里我还有GatewayService:
package com.smdev.gatewayservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class GatewayServiceApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServiceApplication.class, args);
}
@Bean
public RouteLocator getRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
return routeLocatorBuilder.routes()
.route(p -> p
.path("/api/mail/**")
.uri("http://localhost:8001"))
.build();
}
}
这个 API 将从 Angular 前端调用。当我使用 curl 调用 api 时:
curl -X POST -H "Content-type: application/json" -d '{some json data}' localhost:8000/api/mail/feedback
一切正常。但是当我从富裕打电话时:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { ContactUs } from '../model/contact-us';
@Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private httpClient: HttpClient) { }
sendContactUs(dto: ContactUs): Observable<any> {
return this.httpClient.post(`${environment.apiUrl}/mail/feedback`, dto);
}
}
我收到 CORS 错误。我认为原因是我必须在 GatewayService 中配置 CORS,但我没有找到相关信息。
Spring-此处不使用安全性
尝试这样的事情(版本 spring-boot 2.4.9 和 spring-cloud 2020.0.3 上的示例)
在网关上处理 cors 在 spring-cloud-gateway 项目
中添加此 class
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter() {
return new CorsWebFilter(corsConfigurationSource());
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues();
config.addAllowedMethod(HttpMethod.PUT);
config.addAllowedMethod(HttpMethod.DELETE);
config.addAllowedMethod(HttpMethod.GET);
config.addAllowedMethod(HttpMethod.OPTIONS);
config.addAllowedMethod(HttpMethod.POST);
source.registerCorsConfiguration("/**", config);
return source;
}
}
重要的是在交叉请求时检查 cors 上是否存在重复值
return routeLocatorBuilder.routes()
.route(p -> p
.path("/api/mail/**")
// something like this
.filters(f -> f.dedupeResponseHeader("Access-Control-Allow-Origin", "RETAIN_UNIQUE"))
.uri("http://localhost:8001")
)
.route( ... )
.route( ... )
.build();
我必须使用 spring-boot 创建一些微服务。创建了只有一个控制器并配置了 CORS 的 MailService:
package com.smdev.mailservice.controller;
import com.smdev.mailservice.model.dto.EmailAddress;
import com.smdev.mailservice.model.dto.SendMailDTO;
import com.smdev.mailservice.service.MailService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
@Api
@RestController
@RequestMapping("/api/mail")
@CrossOrigin(origins = "*", methods = {RequestMethod.POST, RequestMethod.OPTIONS})
public class MailSendController {
private final MailService mailService;
@Autowired
public MailSendController(MailService mailService) {
this.mailService = mailService;
}
@ApiOperation(value = "Send message from 'Contact Us' form")
@ApiResponses({
@ApiResponse(code = 200, message = "E-Mail send successfully"),
@ApiResponse(code = 400, message = "Invalid data sent", response = ResponseEntity.class)
})
@PostMapping(value = "/feedback", consumes = {MediaType.APPLICATION_JSON_VALUE})
public void feedback(@Valid @RequestBody SendMailDTO sendMailDTO){
mailService.sendMessage(sendMailDTO, EmailAddress.FEEDBACK);
}
}
这里我还有GatewayService:
package com.smdev.gatewayservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class GatewayServiceApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayServiceApplication.class, args);
}
@Bean
public RouteLocator getRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
return routeLocatorBuilder.routes()
.route(p -> p
.path("/api/mail/**")
.uri("http://localhost:8001"))
.build();
}
}
这个 API 将从 Angular 前端调用。当我使用 curl 调用 api 时:
curl -X POST -H "Content-type: application/json" -d '{some json data}' localhost:8000/api/mail/feedback
一切正常。但是当我从富裕打电话时:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { ContactUs } from '../model/contact-us';
@Injectable({
providedIn: 'root'
})
export class ApiService {
constructor(private httpClient: HttpClient) { }
sendContactUs(dto: ContactUs): Observable<any> {
return this.httpClient.post(`${environment.apiUrl}/mail/feedback`, dto);
}
}
我收到 CORS 错误。我认为原因是我必须在 GatewayService 中配置 CORS,但我没有找到相关信息。
Spring-此处不使用安全性
尝试这样的事情(版本 spring-boot 2.4.9 和 spring-cloud 2020.0.3 上的示例)
在网关上处理 cors 在 spring-cloud-gateway 项目
中添加此 classimport org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter() {
return new CorsWebFilter(corsConfigurationSource());
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues();
config.addAllowedMethod(HttpMethod.PUT);
config.addAllowedMethod(HttpMethod.DELETE);
config.addAllowedMethod(HttpMethod.GET);
config.addAllowedMethod(HttpMethod.OPTIONS);
config.addAllowedMethod(HttpMethod.POST);
source.registerCorsConfiguration("/**", config);
return source;
}
}
重要的是在交叉请求时检查 cors 上是否存在重复值
return routeLocatorBuilder.routes()
.route(p -> p
.path("/api/mail/**")
// something like this
.filters(f -> f.dedupeResponseHeader("Access-Control-Allow-Origin", "RETAIN_UNIQUE"))
.uri("http://localhost:8001")
)
.route( ... )
.route( ... )
.build();