ajax跨域请求问题解决方案

  • 什么是跨域
  1.  跨域,指的是从一个域名去请求另外一个域名的资源。即跨域名请求!跨域时,浏览器不能执行其他域名网站的脚本,是由浏览器的同源策略造成的,是浏览器施加的安全限制。
    跨域的严格一点来说就是只要协议,域名,端口有任何一个的不同,就被当作是跨域。 
     

  • 案例
  1. 创建2个项目,分别为: 
     a.basic.com端口号: 8080
     b.basic.com端口号: 8081
     域名可以在本地的host文件中配置: 
    127.0.0.1    a.basic.com
    127.0.0.1    b.basic.com
  2. 在b.basic.com项目中,创建一个Search.java的controller 
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Create by wangxb
     * 2019-08-15 22:58
     */
    @RestController
    @RequestMapping("b")
    public class SearchController {
    
        @RequestMapping("/search")
        public String search(HttpServletResponse response){
           // response.setHeader("Access-Control-Allow-Origin", "*");
            return "success-search";
        }
    }
  3. 在a.basic.com项目中,创建一个index页面 
     
    <!doctype html>
    <html  class="x-admin-sm">
    <head>
        <meta charset="UTF-8">
        <title>index</title>
        <script type="text/javascript" src="/jquery-1.7.2.js"></script>
    </head>
    <body>
    <div>
    
        <div>管理登录</div>
    
    </div>
    <script>
        $(function(){
            $.ajax({
                type:"get",
                url:"http://b.basic.com:8081/b/search",
                dataType:"text",
                success:function(data){
                    alert(data);
                },
                error:function(){
                    alert("error");
                }
            })
        })
    </script>
    </body>
    </html>
    注意: 这里a.basic.com的index页面ajax请求的路径是b.basic.com的地址
     
  4. 访问效果:
     
      
     这里浏览器访问的地址是a.basic.com的页面地址,但是页面中的javascript中请求的是b.basic.com的url。这里就存在跨域,
     
  • 解决跨域方案
  1.  使用设置响应头允许跨域
     在b.basic.com项目中设置: response.setHeader("Access-Control-Allow-Origin", "*"); -- '*'表示允许所有,可以指定
     
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Create by wangxb
     * 2019-08-15 22:58
     */
    @RestController
    @RequestMapping("b")
    public class SearchController {
    
        @RequestMapping("/search")
        public String search(HttpServletResponse response){
            response.setHeader("Access-Control-Allow-Origin", "*");
            return "success-search";
        }
    }
  2. 使用jsonp解决 
     
     修改a.basic.com的页面的ajax方法
     
    <script>
        $(function(){
            $.ajax({
                type:"get",
                url:"http://b.basic.com:8081/b/search",
                dataType : "jsonp",
                jsonp : "jsonpCallback",//服务端用于接收callback调用的function名的参数
                success:function(data){
                    alert(data);
                },
                error:function(){
                    alert("error");
                }
            })
        })

     
     修改b.basic.com的controller
     
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
     * Create by wangxb
     * 2019-08-15 22:58
     */
    @RestController
    @RequestMapping("b")
    public class SearchController {
    
        @RequestMapping("/search")
        public String search(String jsonpCallback) throws Exception{
            return jsonpCallback + "(" + 1000 + ")";
        }
    }

     缺点:前后端都需要修改,且 jsonp只支持get请求,不支持post
  3. 使用HttpClient技术在服务器内部进行请求
     
     思路: 将ajax请求地址改为本地项目的url(a.basic.com),然后再使用HttpClient请求(b.basic.com)。
     相当于发送2次请求,
  4. 使用Nginx搭建API接口网关
     思路
     
     使用nginx分别代理a.basic.com:8080和b.basic.com:8081,客户端页面地址和ajax地址都使用nginx地址,作为代理,由nginx进行转发。 
     
     步骤:
      a、在本地host文件中配置
           
    127.0.0.1    a.basic.com
    127.0.0.1    b.basic.com
    127.0.0.1    api.basic.com
     b、修改a.basic.com页面的ajax请求地址,改为nginx地址
       
     $(function(){
            $.ajax({
                type:"get",
                url:"http://api.basic.com/b/search",
                dataType : "text",
                success:function(data){
                    alert(data);
                },
                error:function(){
                    alert("error");
                }
            })
        })
     c、在nginx.conf配置如下
         
    server {
            listen       80;
            server_name  api.basic.com;
    
            location /a {
                proxy_pass   http://a.basic.com:8080;
                index  index.html index.htm;
            }
    	location /b {
                proxy_pass   http://b.basic.com:8081;
                index  index.html index.htm;
    	}
         }  
    d、测试如下
     
     
      浏览器请求的地址是: http://api.basic.com/a/index    由nginx转发到a.basc.com:8080
          ajax请求的地址是: http://api.basic.com/b/search  由nginx转发到b.basc.com:8081
     
  5.  使用SpringCloud Zuul搭建API接口网关 
     
     和nginx原理一样,将请求地址全部使用网关地址,由网关进行转发
     
     创建服务的注册中心,将a.basic和b.basic.com注册到eureka中去,
     创建服务网关项目,在application.yml中配置如下:
     
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
    server:
      port: 8769
    spring:
      application:
        name: service-zuul
    zuul:
      routes:
        api-a:
          path: /api-a/**
          service-id: a.basic.com  #表示访问zuul的地址+/api-a/**,就会转发到在eureka注册的服务名位a.basic.com的工程下
        api-b:
          path: /api-b/**          #表示访问zuul的地址+/api-b/**,就会转发到在eureka注册的服务名位b.basic.com的工程下
          service-id: b.basic.com
    这里只是个思路,关于springcloud的相关知识,可以参考我的另外一篇文章:SpringCloud基础学习https://blog.csdn.net/xiaobo5264063/article/details/91350355
     
     
  6. 使用spingcloud第二代网关Gateway解决跨域 
     基于全集过滤器实现,允许所有请求跨域。
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.http.server.reactive.ServerHttpResponse;
    import org.springframework.stereotype.Component;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    @Component
    public class CrossOriginFilter implements GlobalFilter {
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
            // 允许跨域请求
            ServerHttpRequest request = exchange.getRequest();
            ServerHttpResponse response = exchange.getResponse();
            HttpHeaders headers = response.getHeaders();
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "POST, GET, PUT, OPTIONS, DELETE, PATCH");
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
            headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*");
            headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");
            return chain.filter(exchange);
    
        }
    }
      
     
     
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值