zoukankan      html  css  js  c++  java
  • json跨域问题

    一、跨域问题的原因:

    1 浏览器的检查

    2 跨域

    3 XMLHttpRequest请求

    二、跨域问题的解决:

    1 禁止浏览器检查:

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

    chrome --disable-web-security --user-data-dir=g:	emp3

    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 }
  • 相关阅读:
    springboot笔记
    SpringBoot
    SpringBoot整合JPA
    Docker
    SpringMVC学习04:异常处理和拦截器
    SpringMVC学习03:文件上传
    SpringMVC学习02:响应数据和结果视图
    Mybatis学习04
    【java基础】初步理解面向对象、类、对象
    【Java基础】方法的重载
  • 原文地址:https://www.cnblogs.com/laowangc/p/8884343.html
Copyright © 2011-2022 走看看