如何解决前端跨域问题
目录
一、什么是跨域,什么是跨域资源共享(CORS)
1.什么是跨域
跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域;具体来讲,同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现;同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收。—百度百科
2.什么是跨域资源共享(CORS)
引用百度百科的解释。CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
3.如何解决跨域问题
3-1.简单的解决方式
为了解决跨域问题,Access-Control-Allow-Origin 该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。在后端添加 Filter 过滤器,设置请求头即可,如下:response.setHeader(“Access-Control-Allow-Origin”, “*”);
3-2.较为完善的解决方式
为了防止骇客利用跨域漏洞进行攻击,一般不写通配符 *,一般写的是请求时Origin字段的值,例如通过 http://localhost:8081 的前端页面访问 http://localhost:8080 的接口,Header头设置如下: response.setHeader(“Access-Control-Allow-Origin”, “http://localhost:8081”);
二、代码实现
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author c
* @version $Revision: 1.4 $ 2023-3-29 下午4:01:27
*/
public class HeadFilter implements Filter {
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void doFilter(ServletRequest request, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) resp;
HttpServletRequest req = (HttpServletRequest)request;
// 获取请求的域(Origin)
String origin = req.getHeader("Origin");
// 如果是自己请求自己(使用测试工具调用接口或直接在浏览器中输入接口访问,非浏览器中的某个网页端中调用接口),则设置 origin 为 requestURL
if (origin == null) {
origin = req.getRequestURL().toString();
}
// 添加被信任url
List<String> allowedOrigins = new ArrayList<>();
// 接口地址
allowedOrigins.add("http://localhost:8080");
// 前端地址
allowedOrigins.add("http://localhost:8081");
// 如果请求的域在被信任的url中,则认可前端的访问;反之,则拒绝访问,跳转至 error.html 页面
Boolean refererFlag = false;
for (String allowedOrigin : allowedOrigins) {
if (origin.startsWith(allowedOrigin)){
refererFlag = true;
break;
}
}
if(refererFlag){
// 解决跨域访问报错问题
response.setHeader("Access-Control-Allow-Origin", origin);
chain.doFilter(request, response);
}else{
response.setHeader("Referrer-Policy", "no-referrer");
request.getRequestDispatcher("error.html").forward(request,response);
}
}
/**
* @see Filter#init(FilterConfig)
*/
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}