首先,我解释一下为什么会产生跨域问题:
跨域问题是由浏览器的同源策略(Same-Origin Policy)引起的安全机制。同源策略要求浏览器限制从一个源加载的文档或脚本与来自其他源的资源进行交互,其中源包括协议、域名和端口号。
具体来说,当浏览器中的 JavaScript 代码试图从一个源(例如 https://www.example.com
)发起 HTTP 请求来获取另一个源(例如 https://api.example.com
)的数据时,浏览器会执行跨域检查,如果请求的目标源不同,就会产生跨域问题。
跨域问题的存在是为了保护用户的隐私和安全,防止恶意网站利用 JavaScript 跨域请求攻击用户的敏感信息。
同源策略(Same-Origin Policy)是浏览器的一种安全策略,它要求浏览器限制从一个源加载的文档或脚本与来自其他源的资源进行交互。同源策略基于域名、协议和端口号进行比较,如果两个页面的这些信息不完全相同,就被认为是跨域。
http://localhost:8080
http://localhost:8081
这两个就是标准的协议相同、域名相同、但是端口号不同。从8080端口发出的请求要访问8081端口的资源,就会产生跨域问题。
跨域限制会导致一些常见的问题,例如在一个页面上使用JavaScript发起AJAX请求获取另一个域名下的数据时,浏览器会阻止这种跨域请求,以确保用户的安全性和隐私。
跨域问题是由浏览器的安全机制引起的,而不是服务器端的限制。服务器端不存在跨域问题,只有浏览器会对跨域请求进行限制。
为了解决跨域问题,可以采用一些方法,如CORS(跨域资源共享)
CORS是跨源资源共享(Cross-Origin Resource Sharing)的缩写,它是一种浏览器机制,用于让服务器授权网页客户端访问跨域资源。在Web开发中,通常情况下浏览器只允许网页从与其本身所在的域名相同的服务器上获取数据,对于其他来源的请求,浏览器会阻止该请求。CORS机制通过特定的HTTP响应头来告知浏览器,哪些源地址可以被允许访问。
在CORS机制中,浏览器会向服务器发送一个预检请求(OPTIONS),以确定是否允许当前网页客户端访问特定的跨域资源。如果服务器允许该请求,就在响应头中加入一组Access-Control-Allow-Origin字段,指明允许访问的域名或IP地址。之后,浏览器就可以安全地将该资源提供给网页客户端了。
需要注意的是,CORS仅适用于浏览器端的跨域请求,而不影响服务器之间的接口请求。
准备一个前端页面发起请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Send HTTP Request</title>
</head>
<body>
<h1>发送HTTP请求示例</h1>
<button οnclick="sendHttpRequest()">发送请求</button>
<script>
function sendHttpRequest() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8080/user', true);
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
console.log('成功收到响应:', xhr.responseText);
} else {
console.error('请求出错:', xhr.status);
}
}
};
xhr.send();
}
</script>
</body>
</html>
创建一个spring boot项目,并创建一个controller接受前端的调用:
@RestController @RequestMapping("/user") public class UserController { @GetMapping public String hello(){ System.out.println("接收到前端发送的请求"); return "后端返回的请求"; }}
将spring boot项目启动,并由前端发起一次请求:
我们打开f12,并点击发送请求。可以很清楚的看到浏览器报by CORS 跨域问题。
这时,我们有很多解决方法。我在这里介绍两种后端常用的方法。
1、在controller类上加上@CrossOrigin注解,
@CrossOrigin是一个用于处理跨域请求的注解,它可以应用在控制器类或控制器方法上。当客户端从不同的源(域名、端口号或协议)发送请求时,就会触发跨域请求。
使用@CrossOrigin注解可以配置允许的跨域请求规则,包括允许的源、允许的HTTP方法、允许的请求头、是否允许发送凭证等。以下是一些常见的参数:
value
:指定允许访问的源,可以是具体的域名或通配符(如"*"
)。origins
:与value
相同,用于指定允许访问的源。methods
:指定允许的HTTP方法,如GET、POST等,默认情况下支持所有方法。allowedHeaders
:指定允许的请求头,默认情况下支持所有请求头。exposedHeaders
:指定可以访问的响应头。allowCredentials
:指定是否允许发送凭证(如Cookie和HTTP认证信息)。maxAge
:指定预检请求的有效期,单位为秒。
通过在控制器类或方法上添加@CrossOrigin注解,可以实现对跨域请求的控制和管理,确保服务器能够正确处理这些请求
2、重写WebMvcConfigurer接口的addCorsMappings方法,并在这个方法里面配置要拦截或放行的请求,并能设置一些参数;
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") //指定允许跨域请求的路径模式为"/**",表示所有的路径都将允许跨域访问。 .allowedOrigins("*") // 允许访问资源的域名 .allowedMethods("*") // 允许的HTTP方法 .allowedHeaders("*") // 允许的请求头 .allowCredentials(false) // 是否允许发送凭证信息 .maxAge(3600); // 预检请求的有效期 } }
以上两种方法都可以完成跨域资源的请求。
启动spring boot项目,做一个测试:
可以看到,现在前端就可以接收到后端返回的数据,并且不报错。
这两种方法都可以解决跨域问题:只不过使用@CrossOrigin注解只能使当前类或方法可以被跨域访问到,而使用WebMvcConfigurer接口的addCorsMappings方法配置是全局生效的。具体使用哪一种方法,还需要根据实际的业务需求。
@CrossOrigin注解和重写WebMvcConfigurer接口的addCorsMappings方法可以同时使用。不过需要注意的是,如果同时使用了这两种方式,实际生效的跨域规则将以addCorsMappings方法中配置的为准。