1.什么是跨域
跨域是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。
2.同源策略
同源策略是一种安全策略,它用于限制一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互。它是浏览器最核心也最基本的安全功能,现在所有支持 JavaScript 的浏览器都会使用这个策略。
2.1限制:
- Cookie、LocalStorage 和 IndexDB 无法读取
- DOM和JS对象无法获得
- AJAX 请求不能发送
3.解决方法
3.1 JSONP
JSONP 只支持 GET 请求,不支持 POST 请求,
原理:网页通过添加一个 <script>
标签来实现跨域请求。这个 <script>
标签的 src
属性指向一个需要请求的 URL,该 URL 返回的数据被当作 JavaScript 代码执行。
缺点:只支持get,不支持post;
因为 POST 请求的数据会被放在 HTTP 请求的 body 中,而 body 是属于同源策略的。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP Demo</title>
</head>
<body>
<button id="getDataBtn">获取数据</button>
<div id="result"></div>
<script src="http://example.com/data.js"></script>
<script>
document.getElementById('getDataBtn').addEventListener('click', function() {
var script = document.createElement('script');
script.src = 'http://example.com/data?callback=handleResponse';
document.body.appendChild(script);
});
function handleResponse(data) {
document.getElementById('result').innerHTML = JSON.stringify(data);
}
</script>
</body>
</html>
3.2 CORS
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
3.2.1创建一个名为CORSFilter的Java类,并实现javax.servlet.Filter接口。
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CORSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化代码
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 设置允许跨域访问的源
httpResponse.setHeader("Access-Control-Allow-Origin", "*");
// 设置允许跨域访问的方法
httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
// 设置允许跨域访问的头信息
httpResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
// 继续处理请求
chain.doFilter(httpRequest, httpResponse);
}
@Override
public void destroy() {
// 销毁代码
}
}
3.2.2 在web.xml文件中配置CORSFilter过滤器。
<filter>
<filter-name>CORSFilter</filter-name>
<filter-class>com.example.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.3 PROXY
3.3.1 proxy 代理跨域(让服务器代理跨域)
3.3.2 解决原理
- 在浏览器同源设置一个代理服务器
- 把本该发送给目标服务器的请求发送给代理服务器
- 由代理服务器转发请求给目标服务器,目标服务器会把响应给代理服务器,代理服务器再把响应给到浏览器
3.3.3使用Nginx实现代理
-
打开Nginx配置文件,通常是位于
/etc/nginx/nginx.conf。
-
修改nginx配置文件:
//修改nginx配置文件:nginx--conf--nginx.conf server { listen 80; server_name example.com; location /api/ { proxy_pass http://backend:3000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; add_header 'Access-Control-Allow-Origin' '*'; } }
在上面的代码中,我们创建了一个名为example.com的服务器块,并在其中添加了一个location块,用于匹配需要跨域访问的请求。在该location块中,我们使用proxy_pass指令将请求转发到后端服务器上,并使用add_header指令设置了响应头中的Access-Control-Allow-Origin字段为*,以允许来自任何源的跨域访问。