CORS解决前端跨域案例学习

跨域的概念不再解释,直接演示下出现跨域的情况:

前端代码(index.html):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CORS Example</title>
</head>
<body>
    <h1>CORS Example</h1>
    <button id="fetchData">Fetch Data</button>
    <p id="result"></p>

    <script>
        document.getElementById('fetchData').addEventListener('click', () => {
            fetch('http://localhost:4000/data')
                .then(response => response.json())
                .then(data => {
                    document.getElementById('result').innerText = JSON.stringify(data);
                })
                .catch(error => {
                    console.error('Error:', error);
                });
        });
    </script>
</body>
</html>

点击Fetch Data按钮,向http://localhost:4000/data请求数据

后端代码(server.js):

const express = require("express");
const app = express();
const port = 4000;

app.get("/data", (req, res) => {
  res.json({ message: "This is some data from the server." });
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

首先我们直接启动服务器:

node server.js

打开浏览器直接输入http://localhost:4000/data 回车,可以返回数据,而且没有任何错误
在这里插入图片描述

此时,我们通过vs code 中的插件 live server打开index.html,这种方式的含义是,本地启动一个开发服务器,域名为http://127.0.0.1:5501,当前位置为http://127.0.0.1:5501/index.html
在这里插入图片描述

Access to fetch at ‘http://localhost:4000/data’ from origin ‘http://127.0.0.1:5501’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

点击按钮时,报错,意思是说,我们当前所在域名为http://127.0.0.1:5501,去请求了一个非同源的资源http://localhost:4000/data,因为是非同源的,出现了跨域情况,这时候被浏览器拦截了,可以发现响应的状态码是200,ok 的
在这里插入图片描述

解决:

通过手动设置Access-Control-Allow-Origin和其他CORS相关的头部来解决跨域问题。

后端代码(server.js)

const express = require('express');
const app = express();
const port = 4000;

app.get('/data', (req, res) => {
    // 设置CORS头部
    res.setHeader('Access-Control-Allow-Origin', '*'); // 允许所有来源(跨域)
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); // 允许的HTTP方法
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); // 允许的头部
    res.json({ message: 'This is some data from the server.' });
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});

我们针对要访问的资源路径 http://localhost:4000/data,配置该资源对于跨域请求的限制。

  1. Access-Control-Allow-Origin: 表示的是可以被来自哪些域的请求访问到。
    该头部指定了允许跨域访问的域。可以设置为特定的域名(比如本例中http://localhost:5501),或使用*表示允许任何域名访问。
  2. Access-Control-Allow-Methods:该头部指定了允许的HTTP方法。例如,可以允许GET、POST、PUT、DELETE等方法。
  3. Access-Control-Allow-Headers:该头部指定了前端在请求中允许使用的自定义头部字段。例如,如果请求中包含Content-Type或Authorization头部,则需要在这里指定。

之后,我们就可以访问到该资源
在这里插入图片描述

处理预检请求(OPTIONS)

某些请求(如带有自定义头部的POST请求)会触发浏览器的“预检请求”(OPTIONS方法)。预检请求的作用是让浏览器先确认服务器是否允许跨域访问

简单请求:

请求方法为:GET、POST、HEAD,请求头 Content-Type 为:text/plain、multipart/form-data、application/x-www-form-urlencoded 的就属于 “简单请求” 不会触发 CORS 预检请求。

非简单请求:

使用的HTTP方法超出了GET、POST、HEAD,如PUT、DELETE等,请求头的 Content-Type 为 application/json 就会触发 CORS 预检请求,这里也会称为 “非简单请求”。

特点:
在实际请求发送之前,浏览器会自动发起一个OPTIONS请求,这就是所谓的预检请求。预检请求用来向服务器询问实际请求是否被允许。

服务器必须正确响应预检请求:服务器需要在预检请求中返回正确的CORS头部,以允许实际请求的发送。

示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Non-Simple Request Example</title>
</head>
<body>
    <h1>Non-Simple Request Example</h1>
    <button id="sendRequest">Send Non-Simple Request</button>
    <p id="response"></p>

    <script>
        document.getElementById('sendRequest').addEventListener('click', () => {
            fetch('http://localhost:4000/data', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': 'Bearer some-token' // 自定义头部
                },
                body: JSON.stringify({ key: 'value' }) // 请求体
            })
            .then(response => response.json())
            .then(data => {
                document.getElementById('response').innerText = JSON.stringify(data);
            })
            .catch(error => {
                console.error('Error:', error);
            });
        });
    </script>
</body>
</html>

后端:

const express = require('express');
const app = express();
const port = 4000;

app.use(express.json()); // 解析JSON请求体

// 处理预检请求,设置CORS头部并返回204 No Content状态码,表明服务器允许实际请求的发送。
app.options('/data', (req, res) => {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'POST');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    res.sendStatus(204); // 204 No Content
});
 
// 处理实际的POST请求,并返回JSON数据
app.post('/data', (req, res) => {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.json({ message: 'Data received successfully', receivedData: req.body });
});

app.listen(port, () => {
    console.log(`Server running at http://localhost:${port}`);
});

在点击按钮之后,可以发现发送了两次网络请求,第一次为预检请求,第二次为post请求
在这里插入图片描述
options请求:
在这里插入图片描述

在这里插入图片描述

以下是一个完整的Java和JavaScript使用CORS解决跨域问题的代码示例: Java后端代码(使用Spring Boot框架): ```java @RestController public class ApiController { @GetMapping("/data") public ResponseEntity<String> getData() { // 处理请求逻辑 String responseData = "This is the response data"; return ResponseEntity.ok(responseData); } } ``` JavaScript前端代码: ```javascript var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://localhost:8080/data', true); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.setRequestHeader('Origin', 'http://example.com'); // 请求源 xhr.withCredentials = true; // 允许发送Cookie xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { var response = JSON.parse(xhr.responseText); console.log(response); // 处理响应 } }; xhr.send(); ``` 在上述示例中,Java后端使用Spring Boot框架创建了一个简单的RestController,其中包含一个处理GET请求的方法`getData()`。该方法返回一个字符串作为响应数据。 在JavaScript前端,使用XMLHttpRequest对象发送了一个GET请求到Java后端的`/data`路径。在请求头中设置了`Content-Type`和`Origin`字段,其中`Origin`字段指定了请求源。还设置了`withCredentials`属性为true,以允许发送Cookie。在接收到响应后,可以通过处理`xhr.responseText`来获取响应数据。 请确保将Java后端代码部署在localhost:8080上,并将JavaScript前端代码部署在一个不同的源(例如http://example.com)上以进行跨域请求。 这个示例演示了如何使用Java和JavaScript中的CORS解决跨域问题。在实际应用中,你需要根据你的需求和框架进行适当的配置和处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值