【问题标题】:CORS header ‘Access-Control-Allow-Origin’ missing REACTCORS 标头“Access-Control-Allow-Origin”缺少 REACT
【发布时间】:2021-07-15 01:54:54
【问题描述】:

我正在 Spring Boot 之上构建一个 React 应用程序。当我尝试向 localhost:8080 发出 put 请求时,我的浏览器上出现了这些错误

跨域请求被阻止:同源策略不允许读取位于 http://localhost:8080/products 的远程资源。 (原因:CORS 标头“Access-Control-Allow-Origin”缺失)。

跨域请求被阻止:同源策略不允许读取位于 http://localhost:8080/products 的远程资源。 (原因:CORS 请求没有成功)

我已经在我的服务器端为 localhost 3000 设置了@CrossOrigin。

一段时间以来一直试图通过添加标头、代理甚至在各处使用 Firefox CORS 来解决此问题。似乎没有任何效果。

请看下面我的前端代码

import React, { Component } from "react";
import { Card, Form, Button } from "react-bootstrap";
import axios from "axios";
import Toasting from "./Toasting";
export default class AddProducts extends Component {
  constructor(props) {
    super(props);
    this.state = this.startState;
    this.state.toast = false;
    this.productChange = this.productChange.bind(this);
    this.submitProduct = this.submitProduct.bind(this);
    var config = {
            headers: {'Access-Control-Allow-Origin': '*'}
        };
  }

  startState = { id: "", name: "", brand: "", made: "", price: "" };

  componentDidMount() {
    const productId = this.props.match.params.id;
    if (productId) {
      this.findProductById(productId);
    }
  }

  findProductById = (productId) => {
    axios
      .get("http://localhost:8080/products/" + productId)
      .then((response) => {
        if (response.data != null) {
          this.setState({
            id: response.data.id,
            name: response.data.name,
            brand: response.data.brand,
            made: response.data.madein,
            price: response.data.price,
          });
        }
      })
      .catch((error) => {
        console.error("Error has been caught: " + error);
        console.log(error);
      });
  };

  reset = () => {
    this.setState(() => this.startState);
  };

  submitProduct = (event) => {
    //Prevent default submit action
    event.preventDefault();

    const product = {
      id: this.state.id,
      name: this.state.name,
      brand: this.state.brand,
      madein: this.state.made,
      price: this.state.price,
    };


    axios.post("http://localhost:8080/products", product)

    .then((response) => {
      if (response.data != null) {

        this.setState({ toast: true });
        setTimeout(() => this.setState({ toast: false }), 3000);
      } else {
        this.setState({ toast: false });
      }
    });
    this.setState(this.startState);
  };

  productChange = (event) => {
    this.setState({
      [event.target.name]: event.target.value,
    });
  };

  productList = () => {
    return this.props.history.push("/");
  };

  updateProduct = event => {
    //Prevent default submit action
    event.preventDefault();

    const product = {
      id: this.state.id,
      name: this.state.name,
      brand: this.state.brand,
      madein: this.state.made,
      price: this.state.price,
    };

    ***************THIS IS WHERE THE ERROR IS**********************************************
    axios.put("http://localhost:8080/products", product, this.config).then((response) => {

      if(response.data != null) {
        this.setState({ toast: true });
        setTimeout(() => this.setState({ toast: false }), 3000);
        setTimeout(() => this.productList(), 3000);
      } else {
        this.setState({ toast: false });
      }
    });
    this.setState(this.startState);
  };

  render() {
    const { name, brand, made, price } = this.state;
    return (
      <div>
        <div style={{ display: this.state.toast ? "block" : "none" }}>
          <Toasting
            toast={this.state.toast}
            message={"Product has been successfully saved!!!"}
            type={"success"}
          />
        </div>

        <Card className={"border border-dark bg-dark text-white"}>
          <Card.Header align="center">
            {" "}
            {this.state.id ? "Update a Product" : "Add a Product"}
          </Card.Header>
          <Form
            onSubmit={this.state.id ? this.updateProduct : this.submitProduct}
            id="productFormId"
            onReset={this.reset}
          >
            <Card.Body>
              <Form.Row>
                <Form.Group controlId="formGridName">
                  <Form.Label>Product Name</Form.Label>
                  <Form.Control
                    required
                    autoComplete="off"
                    type="text"
                    name="name"
                    value={name}
                    onChange={this.productChange}
                    required
                    autoComplete="off"
                    className={"bg-dark text-white"}
                    placeholder="Enter Product Name"
                  />
                </Form.Group>
              </Form.Row>
              <Form.Row>
                <Form.Group controlId="formGridBrand">
                  <Form.Label>Brand</Form.Label>
                  <Form.Control
                    required
                    autoComplete="off"
                    type="text"
                    name="brand"
                    value={brand}
                    onChange={this.productChange}
                    className={"bg-dark text-white"}
                    placeholder="Enter Brand Name"
                  />
                </Form.Group>
              </Form.Row>
              <Form.Row>
                <Form.Group controlId="formGridMade">
                  <Form.Label>Made</Form.Label>
                  <Form.Control
                    required
                    autoComplete="off"
                    type="text"
                    name="made"
                    value={made}
                    onChange={this.productChange}
                    className={"bg-dark text-white"}
                    placeholder="Made in"
                  />
                </Form.Group>
              </Form.Row>
              <Form.Row>
                <Form.Group controlId="formGridPrice">
                  <Form.Label>Price</Form.Label>
                  <Form.Control
                    required
                    autoComplete="off"
                    type="text"
                    name="price"
                    value={price}
                    onChange={this.productChange}
                    className={"bg-dark text-white"}
                    placeholder="Product Price"
                  />
                </Form.Group>
              </Form.Row>
            </Card.Body>
            <Card.Footer>
              <Button size="sm" variant="success" type="submit">
                {this.state.id ? "Update" : "Submit"}
              </Button>{" "}
              <Button size="sm" variant="info" type="reset">
                Undo
              </Button>{" "}
              <Button
                size="sm"
                variant="info"
                type="button"
                onClick={this.productList.bind()}
              >
                Products
              </Button>
            </Card.Footer>
          </Form>
        </Card>
      </div>
    );
  }
}

请看下面我的产品控制器类服务器端

package ie.sw.spring;

import java.util.List;
import java.util.NoSuchElementException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.CrossOrigin;


@RestController
@CrossOrigin("http://localhost:3000")
public class ProductController {

    @Autowired
    private ProductService service;

    @GetMapping("/products")
    public List<Product> list() {
        return service.listAll();
    }

    // Get products by their id
    @GetMapping("/products/{id}")
    public ResponseEntity<Product> get(@PathVariable Long id) {
        try {

            Product product = service.get(id);
            return new ResponseEntity<Product>(product, HttpStatus.OK);

        } catch (NoSuchElementException e) {

            return new ResponseEntity<Product>(HttpStatus.NOT_FOUND);
        }

    }

    // Handle post requests
    @PostMapping("/products")
    public void add(@RequestBody Product product) {
        service.save(product);
    }

    // Update a product
    @PutMapping("/products/{id}")
    public ResponseEntity<?> update(@RequestBody Product product, @PathVariable Long id) {
        try {
            Product existProduct = service.get(id);
            service.save(product);
            return new ResponseEntity<>(HttpStatus.OK);
        } catch (NoSuchElementException e) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }

    }
    
    @DeleteMapping("/products/{id}")
    public void delete(@PathVariable Long id) {
        service.delete(id);
    }

}

【问题讨论】:

  • 您不应从前端附加 CORS headers。所以,删除它。之后,您需要确保 URL http://localhost:8080/products/SOME_ID_HERE" 在 postman 之类的工具中有效。只有在它适用于邮递员之后,您才应该调试 CORS 问题。那么,它对邮递员有效吗?

标签: reactjs spring spring-boot react-native cors


【解决方案1】:
***************THIS IS WHERE THE ERROR IS**********************************************
    axios.put("http://localhost:8080/products", product, this.config).then((response) => {
       ...
    }

    @PutMapping("/products/{id}")
    public ResponseEntity<?> update(@RequestBody Product product, @PathVariable Long id) {
       ...
    }

我认为您在使用axios.put 创建请求时错过了路径变量。您应该删除 @PathVariable Long id 或者您必须在请求中传递 id。

Option 1

axios.put("http://localhost:8080/products/" + productId, product, this.config).then((response) => {
   ...
}

@PutMapping("/products/{id}")
public ResponseEntity<?> update(@RequestBody Product product, @PathVariable Long id) {
   ...
}  

Option 2

axios.put("http://localhost:8080/products", product, this.config).then((response) => {
   ...
}

@PutMapping("/products")
public ResponseEntity<?> update(@RequestBody Product product) {
   ...
}  

另外,更改@CrossOrigin 如下

@CrossOrigin(origins = "http://localhost:3000", methods = {RequestMethod.OPTIONS, RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE}, allowedHeaders = "*", allowCredentials = "true")

你可能也看过here

【讨论】:

    【解决方案2】:

    您是否尝试将 "proxy": "http://localhost:8080" 添加到 package.json 文件中。这对我有帮助。我遇到了同样的问题。

    【讨论】:

    • 我确实什么都没做
    • 您是否尝试过创建自定义服务器并设置代理?
    • 不,我该怎么办?
    • 你的后端是 NodeJS/Express.js 吗?
    • 嗯,我没有使用 Spring 的经验,所以我无法帮助你,但你应该再次检查你的 Spring 配置。也许后端有东西阻塞。您也可以尝试将{"Access-Control-Allow-Headers", "X-Requested-With"} 添加到标题中。
    【解决方案3】:

    @CrossOrigin("http://localhost:3000")

    错了,试试

    @CrossOrigin("http://localhost:8080")

    【讨论】:

      【解决方案4】:

      我已经在我的服务器端为 localhost 3000 设置了@CrossOrigin。

      跨域请求被阻止:同源策略不允许读取 http://localhost:8080/products 上的远程资源。 (原因:CORS 缺少标头“Access-Control-Allow-Origin”)。

      您的错误是针对localhost:8080。

      解决方案:

      1. 在你的服务器端设置localhost:8080。
      2. 你可以在你的服务器端设置*,这是不推荐的,它 设置所有网址。
      3. 或者另一种解决方案是将前端应用程序中的端口更改为 一个你放在背后的。

      【讨论】:

        【解决方案5】:

        如果您只是尝试在本地运行,您是否尝试过 chrome 插件?

        https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf

        【讨论】:

          【解决方案6】:
          【解决方案7】:

          两个可能的答案:

          1. 在您的 WebConfig 文件中配置 cors。从春天开始Documentation

          你的方法是这样的:

          public void addCorsMappings(CorsRegistry registry) {
          
              registry.addMapping("/**")
                  .allowedOrigins("https://localhost:3000/**")
                  .allowedMethods("PUT", "DELETE","GET","POST");
              // Add more mappings...
          }
          
          1. 为了进行测试,请将您的 @CrossOrigin 更改为所有来源:

            @CrossOrigin(origins =*)

          如果它有效,那么它只是某个地方的一个细节。你能测试一下并告诉我们吗?

          查看文档,他们总是留下明确的'origins="address"'。在您的事业中,它将是:

            @CrossOrigin(origins ="http://localhost:3000")
          

          【讨论】:

          • 在CrossOrigin,value 是aliased 到origins 所以我认为@CrossOrigin("http://localhost:3000") 和@CrossOrigin(origins ="http://localhost:3000") 应该做同样的想法,不是吗?
          • 是的。是一样的,但是当我遇到一些麻烦的时候,我什么都清楚了。这就是为什么我在最后一个论点中说的原因
          【解决方案8】:

          使用

          @CrossOrigin(origins = "http://localhost:3000")
          

          【讨论】:

          • 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。
          • 另一个答案已经建议使用@CrossOrigin
          • 在CrossOrigin,value 是aliased 到origins 所以我认为@CrossOrigin("http://localhost:3000") 和@CrossOrigin(origins ="http://localhost:3000") 应该做同样的想法,不是吗?
          猜你喜欢
          • 2018-03-28
          • 2019-02-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-01-05
          • 2021-12-07
          • 2023-03-21
          • 2020-11-12
          相关资源
          最近更新 更多