一、跨域问题的原因:

1 浏览器的检查

2 跨域

3 XMLHttpRequest请求

二、跨域问题的解决:

1 禁止浏览器检查:

使用dos命令,在启动浏览器的时候,加一个参数:

chrome --disable-web-security --user-data-dir=g:\temp3

2 JSONP:

JSONP是什么:JSONP是一种协议
JSONP解决跨域的时候后台代码需要改变吗:需要。
需要加一个切面:@ControllerAdvice
并且让这个类要继承AbstractJsonpResponseBodyAdvice
并且重写构造方法JsonpAdvice(){
super("callback");
}
JSONP的实现原理:
JSONP的弊端:
服务器需要改动代码
只支持GET
发送的不是XHR请求

3 请求是跨域的与隐藏跨域:

被调用方解决:
服务器端实现:
配置Filter:

 @Bean
public FilterRegistrationBean registerFilter(){
  FilterRegistrationBean bean=new FilterRegistrationBean();
  bean.addUrlPattern("/*");
  bean.setFilter(new CrosFilter());
}

创建一个Filter:

 public class CrosFilter implements Filter{
  @Override
  public void init(FilterConfig filterConfig) throws ServletException{
  }
  @Override
  public void doFilter(ServletRequest request,ServletResponse response,FilterChain filterChain)throws IOException, ServletException{
  HttpServletResponse res=(HttpServletResponse)response;
  res.addHeader("Access-Control-Allow-Origin","http://localhost:8081");
  res.addHeader("Access-Control-Allow-Methods","GET");
  res.addHeader("Access-Control-Allow-Headers","Content-Type");
  filterChain.doFilter(request,response);
}
}

此处的res.addHeader("Access-Control-Allow-Origin","*");可以使用*来表示所有的域,方法也可以使用*来表示所有的方法。
简单请求和非简单请求:
  工作中比较常见的【简单请求】:
    方法为:GET HEAD POST
    请求header里面:无自定义头、Content-Type为以下几种:
    text/plain
    multipart/form-data
    application/x-www-form-urlencoded
  工作中比较常见的【非简单请求】:
    put,delete方法的ajax请求
    发送json格式的ajax请求
    带自定义头的ajax请求
OPTIONS预检命令:
  OPTIONS预检命令缓存:
  res.addHeader(“Access-Control-Max-Age”,”3600”);//表示在一小时内缓存这个OPTIONS信息,不用每次请求都请求两次。

带Cookie的跨域问题:

  Origin必须是全匹配,不能使用*,必须指定域名;并且需要在Filter里面增加:
  res.addHeader(“Access-Control-Allow-Credentials”,”true”);

带自定义头的跨域问题:

被调用方-Nginx解决方案:
1 配置虚拟文件vhost:在nginx的目录中创建一个文件夹,命名为vhost,并在nginx的配置文件中的最后一行中加入以下代码:include vhost/*.conf,将vhost中的.conf文件加载进来。
2 在vhost文件夹下新建一个文件b.com.conf,使用nginx的语法,在该文件中加入以下内容:

 server{
listen 80; //监听的端口
server_name b.com;
location /{
proxy_pass http://localhost:8080/;
}
}

此时访问b.com便可以代替之前的localhost:8080进行访问。
3 继续在以上文件中添加:

 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-Headers
$http_access_control_request_headers;
if ($request_method=OPTIONS){
return 200;
}
}

Apache配置:
1 打开apache根目录下的conf文件夹下的httpd.conf文件,并搜索vhost,解开LoadModule vhost_alias_module modules/mod_vhost_alias.so
2 继续搜索vhost,解开Include conf/extra/httpd-vhosts.conf
3 打开conf文件夹下的extra文件夹下的httpd-vhosts.conf
4 增加一个虚拟主机,复制一份,并且修改为以下内容:

 <VirtualHost *:80>
ServerName b.com
ErrorLog "logs/b.com-error.log"
CustomLog "logs/b.com-access.log" common
ProxyPass / http://localhost:8080/
</VirtualHost>

5 在httpd.conf文件中解开proxy模块:LoadModule proxy_module modules/mod_proxy.so (140行)
6 在httpd.conf文件中解开proxy http模块:LoadModule proxy_http_module modules/mod_proxy_http.so
7 进入apache的bin目录,双击httpd.exe文件,启动apache。
8 在httpd-vhosts.conf文件中增加响应头:

 <VirtualHost *:80>
ServerName b.com
ErrorLog "logs/b.com-error.log"
CustomLog "logs/b.com-access.log" common
ProxyPass / http://localhost:8080/ #把请求头的origin值返回到Access-Control-Allow-Origin字段
Header always set Access-Control-Allow-Origin "expr=%
{req:origin}" #把请求头的Access-Control-Request-Headers值返回到Access-
Control-Allow-Headers字段
Header always set Access-Control-Allow-Headers "expr=%
{req:Access-Control-Request-Headers}" Header always set Access-Control-Allow-Methods "*"
Header always set Access-Control-Max-Age "3600"
Header always set Access-Control-Allow-Credentials "true" #处理预检命令OPTIONS,直接返回204
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ "/"[R=204,L]
</VirtualHost>

9 在httpd.conf文件中,解开headers模块:LoadModule headers_module modules/mod_headers.so
10 在httpd.conf文件中,打开rewrite模块:LoadModule rewrite_module modules/mod_rewrite.so

Spring框架的跨域解决:

在控制器中使用@CrossOrigin注解

调用方解决-隐藏跨域:

1 在hosts文件中,增加一个虚拟域名:127.0.0.1 b.com a.com
2 在nginx的vhosts文件夹中新建一个a.com.conf,打开:

 server{
listen 80;
server_name a.com;
l ocation /{
proxy_pass http://localhost:8081/;
}
location /ajaxserver{
proxy_pass http://localhost:8080/test/;
}
}
05-11 22:52