解决跨域问题
前言
之前在项目开发过程中,出现并解决了跨域问题。现在来对跨域问题进行一个系统的学习和总结。通过本篇博客可以了解到解决跨域问题有哪些方法,并且详细介绍了CORS方法来解决跨域问题。
跨域问题演示
我们先来演示一下跨域问题。
前端代码:
项目结构:
demo.html代码
<!DOCTYPE html> <html> <head> <title>调用后端接口示例</title> </head> <body> <h1>调用后端接口示例</h1> <button onclick="callBackend()">调用后端接口</button> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="app.js"></script> </html>
app.js代码
function callBackend() { $.ajax({ url: "http://localhost:8100/courseContent/queryAllCourseConent", // 后端接口的URL method: "GET", // 请求方式 success: function(result) { console.log("服务器响应数据:",result); }, error: function(xhr, status, error) { console.log("请求后端接口出错:", error); } }); }
调用接口时出现跨域问题:
关于$.ajax()函数的补充
$.ajax()介绍
$.ajax()是jQuery库提供的一个函数,用于向服务器发起异步HTTP请求。 它可以执行多种类型的HTTP请求,如GET、POST、PUT、DELETE等。 使用$.ajax()函数,我们可以向服务器发送数据并获取响应,而无需刷新整个页面。
$.ajax()函数可以接收多个参数,其中最常用的参数包括:
url:请求的URL地址
method:请求的HTTP方法(例如GET或POST)
data:要发送到服务器的数据
success:请求成功时的回调函数
error:请求失败时的回调函数
$.ajax函数向服务器发送一个GET请求的示例:
$.ajax({ url: "https://example.com/data", method: "GET", success: function(response) { console.log("服务器响应数据:", response); }, error: function(xhr, status, error) { console.log("请求出错:", error); } });
在上面的代码中,我们向https://example.com/data发送了一个GET请求。如果请求成功,我们将响应数据输出到控制台中。如果请求失败,我们将错误信息输出到控制台中。
$.ajax()函数发生get请求怎么传参数
通过$.ajax()函数发起GET请求传递参数可以通过两种方式:
- 将参数拼接到URL中
$.ajax({ url: "https://example.com/data?id=123&name=foo", method: "GET", success: function(response) { console.log("服务器响应数据:", response); }, error: function( error) { console.log("请求出错:", error); } });
在上面的代码中,我们将参数id和name拼接到URL中,以查询字符串的形式传递到服务器。
- 通过data属性传递参数 使用data属性传递参数,它可以是一个对象,也可以是一个序列化后的字符串
$.ajax({ url: "https://example.com/data", method: "GET", data: { id: 123, name: "foo" }, success: function(response) { console.log("服务器响应数据:", response); }, error: function(error) { console.log("请求出错:", error); } });
在上面的代码中,我们使用data属性传递了一个包含id和name属性的对象,jQuery库会将它序列化成查询字符串并拼接到URL中。
使用$.ajax()函数发送post请求
通过$.ajax()函数发起POST请求传递参数可以通过以下两种方式:
- 通过data属性传递参数
$.ajax({ url: "https://example.com/data", method: "POST", data: { id: 123, name: "foo" }, success: function(response) { console.log("服务器响应数据:", response); }, error: function(error) { console.log("请求出错:", error); } });
在上面的代码中,我们使用data属性传递了一个包含id和name属性的对象,jQuery库会将其序列化成请求体中的表单数据,发送到服务器端。
- 通过contentType和data属性传递参数
另一种方式是将data属性序列化成JSON格式的字符串,并设置请求头中的Content-Type为application/json
$.ajax({ url: "https://example.com/data", method: "POST", contentType: "application/json", data: JSON.stringify({ id: 123, name: "foo" }), success: function(response) { console.log("服务器响应数据:", response); }, error: function( error) { console.log("请求出错:", error); } });
在上面的代码中,我们将data属性序列化成JSON格式的字符串,并设置请求头中的Content-Type为application/json。这样服务器端就能够正确解析请求体中的JSON数据了。
需要注意的是,在使用data属性传递参数时,需要根据实际情况选择适合的方式。如果需要向服务器提交表单数据,可以使用第一种方式;如果需要向服务器提交JSON数据,可以使用第二种方式。
什么是跨域问题
当一个Web应用程序在另一个域(域名或ip+端口号)上请求数据时遇到的安全限制问题。
例如:当一个网页尝试从一个不同的域名请求资源(如数据、图片、视频),浏览器将会阻止这个请求。
这是由于浏览器的同源策略,即同一个域名下的页面可以自由的相互访问,但是不同域名之间的访问将受到限制。
这其实是用于保证用户的安全。但是在我们进行开发的过程中,不免会出现访问另一个域名的资源,为了避免这种问题,开发人员可以使用跨域技术,如CORS,JSONP、代理(通过在Web服务器上设置代理服务器,将跨域请求转发给目标服务器,在代理服务器和目标服务器之间实现跨域请求。)、WebSocket、postMessage。
我们这里主要介绍使用CORS来实现跨域。
跨域资源共享CORS
跨域资源共享CORS(Cross-Origin Resource Sharing):是有W3C推荐的跨域资源共享标准。通过在服务器端设置响应头部信息,可以指定允许那些源站点跨域访问。这样可以保证在安全性和便利性之间取得一个平衡,避免恶意站点盗取用户信息等安全问题,同时也方便了跨域访问其他网站的需求。
跨域资源共享CORS原理
跨域资源共享(CORS)的原理是在浏览器和服务器之间增加一个通信环节,通过一系列预检请求和响应头来告诉浏览器那些跨域请求是被允许的。
- 浏览器发送请求是,会在请求头中添加Origin字段,用来表示请求的来源,也就是请求发起网页所在的域(域名或者ip+端口)。
- 服务器接收到请求后,会根据请求头中的Origin字段判断是否允许来源的请求。如果允许,则在响应头中添加Access-Control-Allow-Origin字段,来告诉浏览器那些来源(域名或者ip+端口号)的请求是被允许的。
- 如果请求需要携带Cookie等凭证,服务器还需要再响应头中添加Access-Control-Allow-Credentials字段,并将其设置为true,表示允许浏览器发送包含凭证的跨域请求。
- 如果请求使用了非简单请求方法(如PUT、DELETE、OPTIONS、PATCH、COPY等),则在发送真正的请求先,浏览器会发送一个预检请求OPTIONS,用来询问服务器是否允许该方法的请求。服务器接收到预检验请求后,需要在响应投中添加Access-Control-Allow-Methods字段,用来告诉浏览器那些方法的请求是被允许的。
- 注意:简单请求方法指的是GET、POST、HEAD这三种方法
- 如果请求头需要携带自定义的请求头(如Content-Type、Authorization等),则需要在响应头中添加Access-Control-Allow-Headers字段,用来告诉浏览器那些请求头是被允许的。
使用CORS解决跨域问题
明白CORS的原理之后,我们就有一个明确的解决跨域问题的思路了。可能在不同框架的java项目中使用CORS解决跨域问题的形式不一致,但是解决思路都是一致的。
以spring boot项目为例:
spring boot项目配置跨域
示例代码:
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; @Configuration @EnableWebMvc public class CorsConfiguration implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { //映射所有传入的HTTP请求 registry.addMapping("/**") //允许所有域名的访问 .allowedOrigins("*") //允许所有HTTP方法 .allowedMethods("*") //允许所有请求头 .allowedHeaders("*") //允许跨域访问的最大时间(单位:秒) .maxAge(1800); } }
上述代码中,我们创建了一个名为CorsConfiguration的类并且实现了WebMvcConfigurer接口。
在addCorsMapping()方法中配置允许所有来源(域名或ip+端口号)跨域访问、并且允许所有HTTP方法、允许所有请求头和配置了最大的跨域访问时间。
使用allowedOrigins()方法类配置允许跨域的员,可以指定多个来源,例如:allowedOrigins(“http://localhost:8080”, “https://www.baidu.com”)。
测试
我们可以看到我们成功的调用并且成功拿取到了服务器中的数据。
总结
- 解决跨域问题的方式有很多种,博客目前只是实践了其中一种。
- 了解到解决跨域问题的原理,不论架构怎么变化,那么我们都能够运筹帷幄。