Spring Boot,CORS 问题:对预检请求的响应未通过访问控制检查:它没有 HTTP ok 状态

Posted

技术标签:

【中文标题】Spring Boot,CORS 问题:对预检请求的响应未通过访问控制检查:它没有 HTTP ok 状态【英文标题】:Spring Boot, CORS problem: Response to preflight request doesn't pass access control check: It does not have HTTP ok status 【发布时间】:2021-09-06 15:05:38 【问题描述】:

我有一个 Spring Boot API 作为服务器,我有一个 Angular JS 前端应用程序。从前端我收到此错误:

Access to XMLHttpRequest at 'http://localhost:8080/?latitude=38.902693&longitude=-77.011932' from origin 'http://localhost:8000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

这是我的 spring 应用程序及其配置:

WebConfiguration.java:

package com.example.assignment.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
public class WebConfiguration implements WebMvcConfigurer 

    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**")
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                .allowedOrigins("*")
                .allowedHeaders("Content_Type", "Authorization");
    

ApplicationConfiguration.java:

package com.example.assignment.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApplicationConfiguration 

    @Bean
    public RestTemplate restTemplate() 
        return new RestTemplate();
    

控制器:

package com.example.assignment.chargingStations.controllers;


import com.example.assignment.chargingStations.models.response.ChargingStation;
import com.example.assignment.chargingStations.services.OpenChargeMapService;
import com.example.assignment.chargingStations.services.SecurityService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import java.util.List;

@RestController
public class ChargingStationsController 

    private final OpenChargeMapService openChargeMapService;

    private final SecurityService securityService;

    public ChargingStationsController(OpenChargeMapService openChargeMapService, SecurityService securityService) 
        this.openChargeMapService = openChargeMapService;
        this.securityService = securityService;
    

    @RequestMapping(path = "/nearest-charging-stations", method = RequestMethod.GET)
    public ResponseEntity<List<ChargingStation>> getNearestChargingStations(@RequestHeader(value = "Authorization", required = false) String token,
                                                                            @RequestParam Double latitude,
                                                                            @RequestParam Double longitude) 
        checkToken(token);
        securityService.validateToken(token);
        List<ChargingStation> nearestChargingStationRequests = openChargeMapService.getNearestChargingStations(latitude, longitude);
        return new ResponseEntity<>(nearestChargingStationRequests, HttpStatus.OK);
    

    private void checkToken(String token) 
        if (token == null || token.equals("")) 
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Authorization header is missing.");
        
    

还有 build.gradle:

plugins 
    id 'org.springframework.boot' version '2.5.1'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'


group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories 
    mavenCentral()


dependencies 
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.projectlombok:lombok:1.18.18'
    implementation 'junit:junit:4.13.1'
    implementation 'com.auth0:java-jwt:3.16.0'
    annotationProcessor 'org.projectlombok:lombok:1.18.18'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'


test 
    useJUnitPlatform()

我不知道我做错了什么。允许所有来源和方法。

【问题讨论】:

【参考方案1】:

我猜您的应用程序未处理浏览器发出的预检 OPTIONS 请求 - 您的应用程序可能返回 HTTP 405 响应(不允许使用方法)。

正如您的错误消息所暗示的,如果浏览器的预检 OPTIONS 请求没有得到 HTTP 200 响应,则永远不会发送 GET 请求。

在Response for preflight does not have HTTP ok status in angular查看我对 CORS 工作原理以及为什么需要支持 OPTIONS 请求的解释

解决这个问题的最简单方法可能是添加

spring.mvc.dispatch-options-request=true

到您的 application.properties 文件。这将配置 Spring Boot 为您处理 OPTIONS 请求,因此您无需在控制器中处理它们。

有关这方面的更多信息,请参阅How to handle HTTP OPTIONS requests in Spring Boot?

【讨论】:

以上是关于Spring Boot,CORS 问题:对预检请求的响应未通过访问控制检查:它没有 HTTP ok 状态的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin 和 Spring Boot 中的 CORS 预检错误

CORS 预检选项请求的 403 错误。怎么修?

已被 CORS 策略阻止:对预检请求的响应未通过

Spring Boot Security OAuth Angular 对预检请求的响应没有通过?

Spring Data REST CORS - 如何处理预检选项请求?

将 Spring Security(双向 SSL)配置为仅对 CORS 预检 OPTIONS 请求进行身份验证