ajax跨域完全解决方案
原因:
- 浏览器限制
- 跨域,端口号或ip地址域名不一样。
- XHR(XMLHttpRequest)请求
解决方案一:浏览器禁止检查
chrome --disable-web-security --user-data-dir=g:\temp3
解决方案二:jsonp
//client
var base = "http://localhost:8080/test";
$.ajax({
url: base +"/get1",
dataType: "jsonp",
jsonp: "callback2",
cache:true,
success: function(json){
result = json;
}
});
#server:springboot1.5.8
@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice() {
// TODO Auto-generated constructor stub
super("callback2");
}
}
jsonp原理:发送的请求不是xhr请求,而是script;jsonp的content-type为application/javascript,而不是json。
解决方案三:被调用方解决
- 服务器端解决
##springboot:1.5.8
public class CrosFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletResponse res = (HttpServletResponse) response;
HttpServletRequest req = (HttpServletRequest) request;
res.addHeader("Access-Control-Allow-Origin","*");
res.addHeader("Access-Control-Allow-Methods", "*");
chain.doFilter(request, response);
}
}
-----------------------------------------------------------------
@SpringBootApplication
public class AjaxserverApplication {
public static void main(String[] args) {
SpringApplication.run(AjaxserverApplication.class, args);
}
@Bean
public FilterRegistrationBean registerFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.addUrlPatterns("/*");
bean.setFilter(new CrosFilter());
return bean ;
}
}
-
简单请求与非简单请求
浏览器识别为简单请求时,先请求后判断。非简单请求时,先判断后请求 工作中比较常见的【简单请求】: 方法为: GET HEAD POST 请求header里面无自定义头 Content-Type为以下几种: text/plain multipart/form-data application/x-www-form-urlencoded ------------------------------------------ 工作中常见的【非简单请求】: put,delete方法的ajax请求 发送json格式的ajax请求 带自定义头的ajax请求
-
非简单请求
doFilter(...){ //单独增加允许的自定义请求头 //res.addHeader("Access-Control-Allow-Headers", "Content-Type"); String headers = req.getHeader("Access-Control-Request-Headers"); //缓存预检(options)命令3600秒 res.addHeader("Access-Control-Max-Age", "3600"); // 支持所有自定义头 if (!org.springframework.util.StringUtils.isEmpty(headers)) { res.addHeader("Access-Control-Allow-Headers", headers); } }
-
带cookie
//让ajax带上cookie $.ajax({ type : "get", url: base + "/getCookie", xhrFields:{ withCredentials:true }, success: function(json){ result = json; } });
----------------------------------Access-Control-Allow-Origin:"*"---------------------------------------------
has been blocked by CORS policy: The value of the ‘Access-Control-Allow-Origin’ header in the response
must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’.
The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
//解决
doFilter(...){
String origin = req.getHeader("Origin");
if (!org.springframework.util.StringUtils.isEmpty(origin)) {
//带cookie的时候,origin必须是全匹配,不能使用*
res.addHeader("Access-Control-Allow-Origin", origin);
}
// enable cookie
res.addHeader("Access-Control-Allow-Credentials", "true");
}
-
带自定义请求头
$.ajax({ type : "get", url: base + "/getHeader", headers:{ "x-header1" : "AAA" }, beforeSend: function(xhr){ xhr.setRequestHeader("x-header2","BBB") }, success: function(json){ result = json; } });
--------------------------解决--------------------------
doFilter(...){ String headers = req.getHeader("Access-Control-Request-Headers"); // 支持所有自定义头 if (!org.springframework.util.StringUtils.isEmpty(headers)) { res.addHeader("Access-Control-Allow-Headers", headers); } }
-
服务器端终极解决方案
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException { // TODO Auto-generated method stub HttpServletResponse res = (HttpServletResponse) response; HttpServletRequest req = (HttpServletRequest) request; String origin = req.getHeader("Origin"); if (!org.springframework.util.StringUtils.isEmpty(origin)) { //带cookie的时候,origin必须是全匹配,不能使用* res.addHeader("Access-Control-Allow-Origin", origin); } // res.addHeader("Access-Control-Allow-Origin", "*"); res.addHeader("Access-Control-Allow-Methods", "*"); // res.addHeader("Access-Control-Allow-Headers", "Content-Type"); res.addHeader("Access-Control-Max-Age", "3600"); String headers = req.getHeader("Access-Control-Request-Headers"); // 支持所有自定义头 if (!org.springframework.util.StringUtils.isEmpty(headers)) { res.addHeader("Access-Control-Allow-Headers", headers); } res.addHeader("Access-Control-Max-Age", "3600"); // enable cookie res.addHeader("Access-Control-Allow-Credentials", "true"); chain.doFilter(request, response); }
解决方案四:nginx
server {
listen 80;
server_name abc.com;
location /{
proxy_pass http://localhost:8080/;
add_header Access-Control-Allow-Methods *;
add_header Access-Control-Max-Age 3600;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Origin $http_origin;
#add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers x-header2,x-header1,content-type;
#add_header Access-Control-Allow-Headers * always;
#add_header Access-Control-Allow-Headers $http_access_control_request_headers;
if ($request_method = OPTIONS){
return 200;
}
}
}
解决方案五:apache
解决方案6:spring框架
//这才是大魔王!!!
@CrossOrigin
public class TestController {}
解决方案7:隐藏跨域
server {
listen 80;
server_name a.com;
location /{
proxy_pass http://localhost:8081/;
}
location /ajaxserver{
proxy_pass http://localhost:8080/test/;
}
}
//client
//以相对地址访问,就不存在跨域
var base = "/ajaxserver";