json跨域问题

一、跨域问题的原因:

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:

1 @Bean
2 public FilterRegistrationBean registerFilter(){
3   FilterRegistrationBean bean=new FilterRegistrationBean();
4   bean.addUrlPattern("/*");
5   bean.setFilter(new CrosFilter());
6 }

创建一个Filter:

 1 public class CrosFilter implements Filter{
 2   @Override
 3   public void init(FilterConfig filterConfig) throws ServletException{
 4   }
 5   @Override
 6   public void doFilter(ServletRequest request,ServletResponse response,FilterChain filterChain)throws IOException, ServletException{
 7       HttpServletResponse res=(HttpServletResponse)response;
 8       res.addHeader("Access-Control-Allow-Origin","http://localhost:8081");
 9       res.addHeader("Access-Control-Allow-Methods","GET");
10       res.addHeader("Access-Control-Allow-Headers","Content-Type");
11       filterChain.doFilter(request,response);
12     }
13 }

此处的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的语法,在该文件中加入以下内容:

1 server{
2     listen 80; //监听的端口
3     server_name b.com;
4     location /{
5     proxy_pass http://localhost:8080/;
6      }
7 }

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

 1 location /{
 2     proxy_pass http://localhost:8080/;
 3     add_header Access-Control-Allow-Methods *;
 4     add_header Access-Control-Max-Age 3600;
 5     add_header Access-Control-Allow-Credentials true;
 6 
 7     add_header Access-Control-Allow-Origin $http_origin;
 8     add_header Access-Control-Allow-Headers         
 9     $http_access_control_request_headers;
10     if ($request_method=OPTIONS){
11         return 200;
12     }
13 }

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 增加一个虚拟主机,复制一份,并且修改为以下内容:

1 <VirtualHost *:80>
2     ServerName b.com
3     ErrorLog "logs/b.com-error.log"
4     CustomLog "logs/b.com-access.log" common
5     ProxyPass / http://localhost:8080/
6 </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文件中增加响应头:

 1 <VirtualHost *:80>
 2     ServerName b.com
 3     ErrorLog "logs/b.com-error.log"
 4     CustomLog "logs/b.com-access.log" common
 5     ProxyPass / http://localhost:8080/
 6 
 7     #把请求头的origin值返回到Access-Control-Allow-Origin字段
 8     Header always set Access-Control-Allow-Origin "expr=%        
 9    {req:origin}"
10 
11     #把请求头的Access-Control-Request-Headers值返回到Access-    
12     Control-Allow-Headers字段
13     Header always set Access-Control-Allow-Headers "expr=%
14     {req:Access-Control-Request-Headers}"
15 
16     Header always set Access-Control-Allow-Methods "*"
17     Header always set Access-Control-Max-Age "3600"
18     Header always set Access-Control-Allow-Credentials "true"
19 
20     #处理预检命令OPTIONS,直接返回204
21     RewriteEngine On
22     RewriteCond %{REQUEST_METHOD} OPTIONS
23     RewriteRule ^(.*)$ "/"[R=204,L]
24 </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,打开:

 1 server{
 2     listen 80;
 3     server_name a.com;
 4 l    ocation /{
 5     proxy_pass http://localhost:8081/;
 6     }
 7     location /ajaxserver{
 8     proxy_pass http://localhost:8080/test/;
 9     }
10 }

 

posted @ 2018-04-23 16:57  老王和小杨  阅读(...)  评论(...编辑  收藏