产生跨域的原因就是违背了浏览器的同源策略
同源策略是一个基本的Web安全机制,主要用于保护浏览器中运行的脚本不受恶意网站的攻击。
同源策略要求浏览器只能从同一源(协议、主机和端口)加载的文档和脚本访问彼此之间的内容和API。
例如,如果一个页面来自https://an1234.top,
它就只能通过AJAX或其他方式访问https://an1234.top或其子域名的数据和API,
而不能访问http://an1234.top或其他域名的数据和API。
同源策略能够有效地防止跨站点脚本攻击(XSS)和跨站点请求伪造(CSRF)等网络攻击。
ajax请求一般只能访问同源资源。针对这个问题,我们可以采取以下几种跨域解决方案:
JSONP
JSONP是用于解决跨域的一种常见方法,它利用了HTML的<script>
标签的特性,可以跨域加载一个JavaScript文件。下面是一个JSONP解决跨域的案例:
假设我们有一个网站A,想从另一个网站B获取数据,但是B网站和A网站不在同一个域名下,这时候就会出现跨域问题。
如果B网站允许跨域,我们可以使用XMLHttpRequest (XHR)对象来获取数据,但是如果不允许跨域,则可以使用JSONP来获取数据。
-
在B网站上准备一个处理JSONP请求的接口,例如:http://b.com/data。
-
在A网站上定义一个回调函数,例如:
jsonpCallback
。 -
在A网站上添加如下代码:
//参数data就是接口返回的数据
function jsonpCallback(data) {
console.log(data);
}
//创建了一个<script>标签
var script = document.createElement('script');
//将该标签的src属性设置为B网站的JSONP接口地址
//查询参数callback=jsonpCallback 就是接口的回调函数
//返回的数据包裹在jsonpCallback函数中,并将其作为响应内容返回。
script.src = 'http://b.com/data?callback=jsonpCallback';
document.head.appendChild(script);
需要注意的是,JSONP只支持GET方法,如果需要使用POST方法,则需要通过其他方式实现跨域。此外,JSONP也存在一些安全问题,因此在使用JSONP时需要谨慎处理响应数据。
CORS(Cross-Origin Resource Sharing)
CORS(Cross-Origin Resource Sharing),即跨源资源共享,是一种现代的跨域解决方案,可用于安全地在不同源之间共享资源。
CORS规定了在浏览器和服务器之间如何进行跨域通信。它通过HTTP请求标头来进行控制和配置,具体包括以下几个方面:
-
简单请求:对于一些符合特定要求的请求(如请求方式为GET、POST、HEAD,且没有自定义头信息等),浏览器会自动发送一个CORS请求头(Origin),服务器端通过判断这个头部,决定是否返回Access-Control-Allow-Origin头部,来控制是否允许跨域访问。
-
预检请求:对于非简单请求(如请求方式为PUT、DELETE、PATCH、Content-Type不为text/plain等),浏览器会先发送一个OPTIONS的预检请求(Preflight),服务器端需要返回Access-Control-Allow-Headers、Access-Control-Allow-Methods和Access-Control-Allow-Origin等头部信息来进行配置,来决定是否允许跨域访问。
-
Access-Control-Allow-Origin头部:用于指定允许访问的域名,其值可以为*,表示允许任何域名请求。
-
Access-Control-Allow-Methods头部:用于指定允许访问的HTTP方法。
-
Access-Control-Allow-Headers头部:用于指定允许访问的HTTP头部字段。
除此之外,还可以通过设置Access-Control-Max-Age头部和Access-Control-Expose-Headers头部等来进行更细粒度的配置。
使用案例:
服务端在响应中添加头部 Access-Control-Allow-Origin,
指定允许跨域请求的来源,可以是单个域名,多个域名,或者通配符。
例如,允许所有域名跨域请求可以这样写:
Access-Control-Allow-Origin:*
如果需要带上 Cookie 或者认证信息,
需要在响应头中添加 Access-Control-Allow-Credentials:true;
客户端也需要带上 withCredentials:true 的参数,请求才能携带 Cookie。
Access-Control-Allow-Credentials:true
如果需要自定义请求头,需要在响应头中添加 Access-Control-Allow-Headers,
指定允许跨域请求的自定义请求头,例如:
Access-Control-Allow-Headers:content-type, x-foo-token
如果需要支持 PUT、DELETE 等请求方式,
需要在响应头中添加 Access-Control-Allow-Methods,指定允许跨域请求的方法,例如:
Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS
服务端按照需要设置响应头后,前端发起请求时,需要确保请求允许跨域。在 Ajax 请求中,需要设置 xhr 对象的 withCredentials、contentType 和 headers 属性,以确保请求携带 Cookie、请求类型和自定义请求头。
总之,CORS是一种强大灵活的跨域解决方案,但要注意它可能会增加服务器的负担和网络请求时间,同时开发者还需要关注浏览器和服务器的兼容性问题和安全问题。
代理设置
1.使用代理服务器对请求进行转发也是一种可行的跨域解决方案,可以在我们的服务器上搭建一个代理服务器,然后将请求发送到代理服务器上。代理服务器再将请求转发给真正的服务端,最后再将响应结果返回给前端。
2.Nginx
Nginx 是一款高性能的 Web 服务器,并且可以作为反向代理服务器使用。通过配置 Nginx 反向代理,可以轻松地解决跨域问题。
假如我们想请求http://an1234.top/data 接口,产生跨域,我们就可以使用反向代理
在 Nginx 的配置文件中添加以下代码:
server {
# 监听的端口
listen 80;
# 服务名称
server_name localhost;
location /api/ {
proxy_pass http://an1234.top/;
# 添加了一些 "Access-Control-" 相关的响应头,以便服务器允许跨域请求。
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
}
保存配置文件之后,重启 Nginx,然后在前端项目中就可以访问代理服务器了。
通过访问 http://localhost:80/api/data 就可以拿到数据了, http://localhost:80就是我们配置的端口,通过匹配 /api/ 找到反向代理的ip地址,访问/data拿到服务端的数据。
综上所述,以上就是几种常用的前端跨域解决方案。由于每种解决方案的适用场景不同,所以我们在处理跨域问题时需要根据实际情况进行选择。