跨域产生的原因
1、浏览器的限制
2、跨域,域名不一致,端口不一致
3、XHR(XMLHttpRequest)请求
三个同时存在才有可能产生跨域问题
解决跨域问题的思路
1、浏览器(通过指定参数让浏览器不去做校验,需要改动客户端,意义不大)
2、XHR(通过修改发出请求的类型,通过JSONP,动态创建script,在script中发送请求)
3、跨域
a)修改被调用,让其支持跨域 b)修改调用方,隐藏跨域,使用代理
2.XHR方式
JSONP:JSON的扩充模式,在请求中增加一个约定的参数,用于识别请求是jsonp请求,后台识别到为jsonp的请求时,就以javascript的方式返回
前台请求使用jsonp,后台需要增加jsonp的切入
弊端:1、服务器需要改动 2、只支持get的方法 3、发送的不是XHR请求
$.ajax({ url:"http://127.0.0.1:8080/test/get1", dataType:"jsonp", jsonp:"callback2", success:function(result){ console.log(result); } });
@ControllerAdvice public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice{ public JsonpAdvice() { super("callback2"); } }
3、跨域
跨域请求的请求头中,浏览器会增加Origin字段,保存原来的地址
增加一个filter,为返回的时候在返回头中增加允许跨域的标识
public class CrosFilter implements Filter { @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // TODO Auto-generated method stub HttpServletResponse httpResponse = (HttpServletResponse)response; //指定特定的域 // httpResponse.addHeader("Access-Control-Allow-Origin", "http://127.0.0.1:8090"); //指定所有的域 httpResponse.addHeader("Access-Control-Allow-Origin", "*"); //指定特定的方法 // httpResponse.addHeader("Access-Control-Allow-Methods", "GET"); //指定所有的方法 httpResponse.addHeader("Access-Control-Allow-Methods", "*"); chain.doFilter(request, response); } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }
请求分为两种:简单请求,非简单请求
简单请求:
1、方法为GET、POST、HEAD
2、请求HEAD里面无自定义头,ContentType为:text/plain、multipart/form-data、application/x-www-form-urlencoded
增加Filter在服务端解决跨域问题
public class CrosFilter implements Filter {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpServletRequest httpRequest = (HttpServletRequest) request;
String origin = httpRequest.getHeader("origin");
// 直接从request中获取并设置到response中
if (!"".equals(origin) && origin != null) {
httpResponse.addHeader("Access-Control-Allow-Origin", origin);
}
/*Enumeration enum1 = httpRequest.getHeaderNames();
System.out.println("-----------header----------------->");
while (enum1.hasMoreElements()) {
String key = (String) enum1.nextElement();
String value = httpRequest.getHeader(key);
System.out.println(key + ":" + value);
}
System.out.println("<-----------header-----------------");
String headers = httpRequest.getHeader("Access-Control-Request-Headers");
System.out.println("dd" + headers);
// 支持所有自定义的方法头
if (!"".equals(headers) && headers != null) {
httpResponse.addHeader("Access-Control-Allow-Headers", headers);
}
*/
// 指定特定的域,带cookie的请求需要全匹配
// httpResponse.addHeader("Access-Control-Allow-Origin",
// "http://127.0.0.1:8090");
// 带cookie请求时需要在请求头增加该参数值
httpResponse.addHeader("Access-Control-Allow-Credentials", "true");
// 指定所有的域,为*时不能满足带cookie的请求
// httpResponse.addHeader("Access-Control-Allow-Origin", "*");
// 指定特定的方法
// httpResponse.addHeader("Access-Control-Allow-Methods", "GET");
// 指定所有的方法
httpResponse.addHeader("Access-Control-Allow-Methods", "*");
// 当有options预检命令时
// httpResponse.addHeader("Access-Control-Allow-Headers",
// "Content-Type,x-header1,x-header2");
// 预检命令的缓存时间
httpResponse.addHeader("Access-Control-Max-Age", "3600");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
使用nginx解决跨域问题,增加一个nginx的配置文件
apache解决跨域问题
使用spring框架解决跨域问题,在类或者方法上增加注解@CrossOrigin