關於瀏覽器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代理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM