【问题标题】:How to correct a problem related to the Cors Origin in spring boot with angular 11?如何纠正与角度 11 的弹簧靴中的 Cors Origin 相关的问题?
【发布时间】:2021-06-13 13:03:29
【问题描述】:

我在 Spring Boot 和 Angular 中开发的 API 存在问题。当我尝试用图像录制新的表演时,我总是有与 Cors 跨源标题相关联的相同错误。

这是我的控制器和用于创建 Prestation 的方法

@RestController
@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600)
@RequestMapping("/prestations")
public class PrestationController {

    private byte[] bytes;
    @Autowired
    IPrestationService prestationService;
    @Autowired
    PrestationRepository prestationRepository;
    @Autowired
    ServletContext context;


@PostMapping
    public ResponseEntity<MessageResponse> savePrestaWithImage(@RequestParam("file") MultipartFile file, @RequestParam("prestation")String prestation)
    throws JsonParseException, JsonMappingException, Exception {
        Prestation presta = new ObjectMapper().readValue(prestation, Prestation.class);
        boolean isExist = new File(context.getRealPath("/Images/")).exists();
        if(!isExist){
            new File(context.getRealPath("/Images/")).mkdir();
            System.out.println("dossier créer");
        }
        String filename = file.getOriginalFilename(); // je recupere le nom de l'image
        String newFileName = FilenameUtils.getBaseName(filename)+"."+FilenameUtils.getExtension(filename);
        File serverFile = new File(context.getRealPath("/Images/"+File.separator+newFileName));
        try {
            System.out.println("Image");
            FileUtils.writeByteArrayToFile(serverFile, file.getBytes());
        }catch (Exception e){
            e.printStackTrace();
        }
        presta.setPhoto(newFileName);
        Prestation prestation1 = prestationRepository.save(presta);
        if(prestation1 != null){
            return new ResponseEntity<MessageResponse>(new MessageResponse(""), HttpStatus.OK);
        }else {
            return  new ResponseEntity<MessageResponse>(new MessageResponse("Prestation not saved"), HttpStatus.BAD_REQUEST);
        }

    }

这是我的角度服务

savePrestation(prestation: Prestation): Observable<Prestation> {
    const httpOptions = {
      headers: new HttpHeaders({
        'Content-type ': 'application/json',
        'Acces-Control-Allow-Origin': '/*'
      })
    }
    return this.http.post<Prestation>(this.SAVE_PRESTA, prestation, httpOptions).pipe(
      tap(_ => this.log(`save prestation with id = ${prestation.id}`)),
      catchError(this.handleError<any>('addPresta'))
    );
  }

这是我的角度方法 savePresta

savePresta() {
    const uploadData = new FormData();
    uploadData.append('imageFile', this.selectedFile, this.selectedFile.name);
    this.selectedFile.imageName = this.selectedFile.name;

    this.http.post(this.SAVE_PRESTA + '/upload', uploadData, { observe: 'response' }).subscribe(
      (response) => {
        if (response.status == 200) {
          this.service.savePrestation(this.prestation).subscribe(
            (prestation) => {
              this.prestation = prestation;
              this.goBack();
            });
          console.log('image uploaded successfull');
        } else {
          console.log('image not uploaded sucessfull')
        }
      });
  }

我还是有同样的错误

Access to XMLHttpRequest at 'http://localhost:8080/prestations' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
POST http://localhost:8080/prestations net::ERR_FAILED

ERROR HttpErrorResponse headers: HttpHeaders status: 0 statusText: "Unknown Error" url:"http://localhost:8080/prestations", ok: false …

help me please that days that I block the top I tried everything but nothing helped

【问题讨论】:

  • 我认为您不应该将 'Acces-Control-Allow-Origin': '/*' 传递到 POST 中,但这可能不是主要问题。
  • 是的,迈克尔,你是对的,我绝望地说,希望它能奏效。

标签: angular spring-boot


【解决方案1】:

这是一个 CORS 问题,与安全问题有关。

问题

假设您的前端托管在xxx.com,而后端托管在yyy.com

从浏览器的角度来看,您连接到xxx.com,但向yyy.com 发出请求,这很奇怪。如果yyy.com 没有明确授权从xxx.com 发送请求,浏览器将阻止该请求。

现在,浏览器如何知道yyy.com 授权来自xxx.com 的请求?有飞行前的请求。浏览器执行飞行前请求并期望在响应中找到一些与 CORS 相关的 HTTP 标头。看 ?这是错误信息中写的:Response to preflight request doesn't pass access control check

以下是此类 HTTP 标头的示例:

Access-Control-Allow-Origin: http://toto.example
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400

这里,localhost:4200localhost:8080 被视为 2 个不同的来源

你能做什么?

您有 2 个解决方案:创建代理或设置正确的 HTTP 标头

创建代理

假设您在zzz.com 上创建了一个代理。您的浏览器已连接到zzz.com,并且所有后端调用都针对zzz.com。从您的浏览器的角度来看,没有更多的跨源资源共享。

但是,zzz.com 必须将前端请求重定向到 xxx.com,并将后端请求重定向到 yyy.com。如果您决定所有后端请求都以/api 之类的开头,则可以轻松完成此操作。这将允许您编写一个简单的正则表达式:

  • /api 开头 => 后端
  • else => 前端

幸运的是,在开发环境中,Angular 提供了一个内置的解决方案。你可以看看Proxying to a backend server 它仅包括使用指向文件的 --proxy-config 选项启动 Angular 应用程序,例如:

{
  "/api": {
    "target": "http://localhost:8080",
    "secure": false
  }
}

(在这里,我们假设您所有的后端端点都以/api 开头)

HTTP 标头

这个答案提供了一个带有一些 Angular 配置的解决方案:How to resolve the CORS issue using proxy in angular

永远不要使用Access-Control-Allow-Origin: *

如果您想轻松修改 HTTP Headers 以进行测试,可以安装 Chrome 扩展程序modHeader

注意:当您投入生产时,您会遇到这个问题,因此解决方案的选择必须由您在生产中所需的解决方案来驱动。

【讨论】:

  • 感谢阿诺德的留言。我尝试了你的解决方案,但我仍然有同样的错误。我添加了代理并修改了网址,但没有任何变化。
  • @Diallosouleymane 您是否使用--proxy-config 选项启动了该应用程序?此外,您现在应该向localhost:4200 发出后端请求,并让代理将它们重定向到localhost:8080。查看您的浏览器调试工具,您应该会看到对localhost:4200的请求
【解决方案2】:

在处理 cors 时,我正在使用非常简单的解决方案来开发 Spring Web Services:

  1. 在SpringSecurityConfig中调用cors()方法配置cors。因为 Spring Security 在到达 Controller 之前处理请求:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        // other configs ...
        http.cors();
        // other configs ...
  1. 在每个控制器中我都使用注解@CrossOrigin
@CrossOrigin
@RestController
public class EventController extends BaseController {
}

但是,如果将 @CrossOrigin 移动到 BaseController 是否可行,也许可以简化(我还没有检查过)。

【讨论】:

  • 感谢您的回归。但我已经尝试过这个解决方案,但没有任何改变。
猜你喜欢
  • 2018-10-12
  • 2018-07-10
  • 2017-07-24
  • 2023-03-29
  • 2018-08-09
  • 2019-05-17
  • 2020-08-06
  • 2017-04-29
  • 1970-01-01
相关资源
最近更新 更多