关于浏览器CORS跨域问题的解决方式

1. JSONP方式

原理是通过script标签的跨域特性来绕过同源策略。
具体利用jQuery的ajax属性dataType jsonp jsonpCallback。

2. 前后端设置请求头方式

注:Access-Control-Allow-Headers必须设置具体值,*值无效。

2.1 前端设置

let value = "you will see me.";
let url = "http://127.0.0.1:5688/test";
// 直接打开新窗口不会有跨域问题,只支持GET请求
let newWindow = window.open(url + "?value=" + value, "_blank");
newWindow.onload = function (e) {
	newWindow.document.title = "调用测试服务";
};
$.ajax({
	url: url,
	method: "GET",
	dataType: "JSON",
	data: {value: value},
	crossDomain: true,
	headers: {
		"Access-Control-Allow-Origin": "*",
		"Access-Control-Allow-Methods": "GET,POST,PUT,DELETE,OPTIONS",
		"Access-Control-Allow-Headers": "Content-Type,X-Requested-With,Cookies,Cookie,X-Auth-Token,token,auth,Authorization",
		"Access-Control-Request-Methods": "GET,POST,PUT,DELETE,OPTIONS",
		"Access-Control-Allow-Credentials": true,
		"Access-Control-Max-Age": 86400
	},
	beforeSend: function (xhr) {
		// 同headers
		// xhr.setRequestHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With,Cookies,Cookie,X-Auth-Token,token,auth,Authorization");
	},
	success: function (result, response, status) {
		console.info(result);
	},
	error: function (xhr, state, thrown) {
		layer.alert("服务器出错啦!", {icon: 5});
	}
});

2.2 后端设置

参考1:https://developer.aliyun.com/article/753657
首先对OPTION请求放入HTTP 200的响应内容。
对于Preflight request询问中的的Access-Control-Request-Headers予以通过。

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                FilterChain filterChain) throws ServletException, IOException {
	String orignalHeader = request.getHeader("Origin");

	if (orignalHeader != null ) {
		Matcher m = CORS_ALLOW_ORIGIN_REGEX.matcher(orignalHeader);
		if (m.matches()) {
			response.addHeader("Access-Control-Allow-Origin", orignalHeader);
			response.addHeader("Access-Control-Allow-Credentials", "true");
			response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
			response.addHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
		}
	}

	if ("OPTIONS".equals(request.getMethod())) {
		response.setStatus(HttpServletResponse.SC_OK);
	} else {
		filterChain.doFilter(request, response);
	}
}

参考2:

public class ProcessInterceptor implements HandlerInterceptor {
	@Override
	public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
		httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
		httpServletResponse.setHeader("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With");
		httpServletResponse.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
		httpServletResponse.setHeader("X-Powered-By","Jetty");

		String method= httpServletRequest.getMethod();
		if (method.equals("OPTIONS")) {
			httpServletResponse.setStatus(200);
			return false;
		}
		System.out.println(method);
		return true;
	}
	
	@Override
	public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
	}
	
	@Override
	public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
	}
}

2.3 若有中间代理,如nginx需要添加一些头信息如下,不一定全部都需要。

add_header Access-Control-Allow-Origin "https://04007.com'" always;
add_header Access-Control-Allow-Headers "Content-type,Origin,X-Auth-Token,X-JSON,Cookies,Cookie,Content-Length" always;
add_header Access-Control-Allow-Methods "GET,POST,OPTIONS" always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Max-Age "86400" always;

3. 代理服务器方式

使用代理服务器做路由转发,如nginx代理。

上一篇:Linux bind: Address already in use


下一篇:导出下载模板