Access-Control-Allow-Origin 未添加到 Spring Boot 应用程序的 Rest API 中

问题描述 投票:0回答:1

我创建了一个具有“Spring web”依赖项的新 Spring boot 应用程序。该模板使用Spring boot 3.2.5版本。相关依赖项是:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

创建休息控制器后,我在 Dart / Flutter 客户端中收到 Error: ClientException: XMLHttpRequest error.。在浏览器中访问 URL 工作正常并返回 JSON。

阅读完问题后,我认为服务器配置中缺少 Access-Control-Allow-Origin 标头。

我尝试将其添加到控制器中:

package com.vogella.spring.jsonserver;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import com.vogella.spring.jsonserver.controller.TutorialCategoryProvider;
import com.vogella.spring.jsonserver.model.TutorialCategory;
import com.vogella.spring.jsonserver.model.TutorialLink;

import java.util.List;

@RestController
@CrossOrigin(origins = "*")
public class CategoryController {

    private final TutorialCategoryProvider provider;

    @Autowired
    public CategoryController(TutorialCategoryProvider yourService) {
        this.provider = yourService;
    }
    
    @CrossOrigin(origins = "*")
    @GetMapping("/categories")
    public List<TutorialCategory> get() {
        // Your implementation to fetch all links from your data source
        // For example, from a database or a service
        return provider.getTutorialCategories();
    }
    
}

还尝试将其添加到应用程序的配置中:

package com.vogella.spring.jsonserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@SpringBootApplication
public class RestServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(RestServiceApplication.class, args);
    }
    
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                System.out.println("Called");
                
                registry.addMapping("/**")
                .allowedOrigins("*")
                .maxAge(4800)
                .allowCredentials(false)
                .allowedMethods("POST", "GET", "OPTIONS", "DELETE", "PUT")
                .allowedHeaders("origin", "Content-Type", "X-Requested-With", "X-File-Name", "x-mime-type",
                        "Accept-Encoding", "Authorization", "Content-Range", "Content-Disposition",
                        "Content-Description", "Access-Control-Request-Method", "Access-Control-Request-Headers");
            }
        };
    }

}

但是如果我通过curl 检查此标头,我看不到它:

curl -I http://localhost:8080/categories
HTTP/1.1 200 
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 25 Apr 2024 11:37:39 GMT

有什么我错过的建议吗?

spring spring-boot
1个回答
0
投票

您找错地方了。

浏览器在实际请求之前发送

OPTIONS
请求以获取有关被调用端点的一些信息。响应标头
Access-Control-Allow-Origin
OPTIONS
请求返回,而不是由以下
GET
请求返回。浏览器预先发送的
OPTIONS
请求也可以用curl复制:

curl --verbose --request OPTIONS "[endpoint being called]" --header "Origin: [host from which the endpoint is being called]" --header "Access-Control-Request-Method: [http method with which the endpoint is being called]"

因此,在您的情况下,命令行如下所示(我假设 Spring Boot 应用程序为前端和 API 提供服务):

curl --verbose --request OPTIONS "http://localhost:8080/categories" --header "Origin: localhost:8080" --header "Access-Control-Request-Method: GET"

我已经根据您的示例设置了一个小型演示应用程序,curl 命令给出了以下输出:

*   Trying [::1]:8080...
* Connected to localhost (::1) port 8080
> OPTIONS /categories HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/8.4.0
> Accept: */*
> Origin: localhost:8080
> Access-Control-Request-Method: GET
>
< HTTP/1.1 200
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: POST,GET,OPTIONS,DELETE,PUT
< Access-Control-Max-Age: 4800
< Allow: GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH
< Content-Length: 0
< Date: Thu, 25 Apr 2024 21:27:40 GMT
<
* Connection #0 to host localhost left intact

请记住,如果您为 API 添加安全性,即一旦您的 API 需要凭据进行身份验证,

Access-Control-Allow-Origin
标头将不再允许使用通配符,并且您必须显式指定所有可能的引用主机名。

© www.soinside.com 2019 - 2024. All rights reserved.