• 跨域的五种解决方案


    跟多介绍可参考:
    跨域的五种解决方案笔记和相关资料下载

    1. 什么是跨域

    浏览器不允许执行其他网站的脚步(ajax),浏览器的同源策略造成的;
    例如:发起ajax请求时如果IP、端口、协议任一不同,则都属于跨域。

    例如以下案例中,A网站需要请求B网站接口:

    A网站B网站是否跨域说明
    http://192.162.1.1:8080http://192.162.2.2:8080存在跨域IP不同
    http://192.162.1.1:8080http://192.162.1.1:8081存在跨域端口不同
    http://192.162.1.1:8080https://192.162.1.1:8080存在跨域协议不同
    http://192.162.1.1:8080http://192.162.1.1:8080不存在跨域(协议、ip、端口)全部相同

    2. 演示跨域问题

    步骤:
    首先在右上角下载本章节相关资料;

    1. 将demo.html 放入Nginx的html目录中_(默认已经放进去了)_,双击nginx.exe启动Nginx, –启动Nginx
    2. 运行jar包 java -jar kexuekt01.jar, 或通过idea打开kexuekt01项目, – 启动项目
    3. 浏览器访问:http://127.0.0.1/demo.html – 看效果
      F12打开浏览器控制台查看跨域error错误信息`:
      file

    重要知识点:存在跨域时Java接口是可以正常进行业务处理的,只是浏览器不能接收后台返回的数据,并在图 1浏览器控制台输出的跨域错误。

    3. 解决跨域的五种方法

    1. jsonp
    2. 内部HttpClient远程调用
    3. nginx反向代理
    4. 设置响应头允许跨域 response.setHeader(“Access-Control-Allow-Origin”, “*”);
    5. SpringBoot注解@CrossOrigin

    3.1 Jsonp解决跨域演示

    前端代码

     $.ajax({
         type:"get",
                 dataType:"jsonp",
                 jsonp:"callback",//请求中重写回调函数的名字
                 url:"http://127.0.0.1:8080/kexue/user",
                 success:function (data) {
             alert(data.response);
         }
     }, 'json');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    后台代码

    1. 后台需要接收的jsonp:"callback"中的"callback"参数,
    2. 返回参数格式必须为:callback({object});
    @RequestMapping("/kexue/user")
    public String demo(String callback) {
    			JSONObject obj = JSONUtil.createObj();
    			obj.put("code", 200);
    			obj.put("response", "调用成功");
    			// 返回格式:callback({object});
    			return callback + "(" + obj + ")";
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    说明

    Jsonp的使用方式较为麻烦,解决跨域一般不会使用该方法。

    3.2 内部HttpClient远程调用

    启动两个后台

    端口1:8080(自己公司的项目解决了跨域问题)
    端口2:8081(模拟第三方项目接口,没有解决跨域问题)

    8080端口项目

    @CrossOrigin // 跨域注解
    @RestController
    public class Demo1 {
    
    		@RequestMapping("/kexue/user")
    		public JSONObject demo() {
    			String body = HttpRequest.get("127.0.0.1:8081/kexue/user2").execute().body();
    			JSONObject obj = JSONUtil.parseObj(body);
    			return obj;
    		}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    8081端口项目(第三方接口)

    @RequestMapping("/kexue/user2")
    public JSONObject demo() {
    			JSONObject obj = JSONUtil.createObj();
    			obj.put("code", 200);
    			obj.put("response", "第三方接口");
    			return obj;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注:修改端口号,便于测试 -Dserver.port=8081

    说明

    HttpClient这种方式适合调用第三方接口。
    例如:调用第三方接口时,如果前端直接调用第三方接口会报跨域问题(第三方接口没有解决跨域问题),那么就只能通过后台HttpClient的方式进行调用。
    file

    3.3 Nginx反向代理

    前端代码

    $.ajax({
          type:"get", 
          url:"http://127.0.0.1:80/kexue/user", 
          success:function (data) {
              //请求成功后的处理
    			alert(data.response);
          }
    }, 'json');
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    后端代码

    @RequestMapping("/kexue/user")
    public JSONObject demo() {
        JSONObject obj = JSONUtil.createObj();
        obj.put("code", 200);
        obj.put("response", "调用成功");
        // 返回格式:callback({object});
        return obj;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    nginx.conf

    worker_processes  1;
    events {
        worker_connections  1024;
    }
    http {
        include       mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        keepalive_timeout  65;
    
        server {
            listen       80;
            server_name  localhost;
    
            location / {
                root   html;
                index  index.html index.htm;
            }
    		
    		#拦截所有以/kexue开头的请求
    		location /kexue {
    			index  proxy_set_header Host $host;
    			index  proxy_set_header X-Real-IP $remote_addr;
    			index proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    			proxy_pass http://127.0.0.1:8080; #后端服务地址
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    说明

    使用Nginx方向代理的前提是,前端代码(vue)需要和Nginx服务在一台物理机上;如果满足以上条件,就优先考虑通过Nginx反向代理来解决跨域问题。

    3.4 设置响应头允许跨域

    前端代码

    $.ajax({
          type:"get", 
          url:"http://127.0.0.1:8080/kexue/user", 
          success:function (data) {
              //请求成功后的处理
    			alert(data.response);
          }
    }, 'json');	
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    后端代码

    @RequestMapping("/kexue/user")
    public JSONObject demo(HttpServletResponse response) {
        JSONObject obj = JSONUtil.createObj();
        obj.put("code", 200);
        obj.put("response", "调用成功");
        // *允许所有网站跨域
        response.setHeader("Access-Control-Allow-Origin", "*");
        return obj;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    说明

    通常都是在拦截器中来配置“设置响应头允许跨域”。

    3.5 @CrossOrigin注解

    前端代码

    $.ajax({
          type:"get", 
          url:"http://127.0.0.1:8080/kexue/user", 
          success:function (data) {
              //请求成功后的处理
    			alert(data.response);
          }
    }, 'json');	
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    后端代码

    @CrossOrigin // 跨域注解
    @RestController
    public class Demo1 {
    
        @RequestMapping("/kexue/user")
        public JSONObject demo() {
            JSONObject obj = JSONUtil.createObj();
            obj.put("code", 200);
            obj.put("response", "调用成功");
            return obj;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    说明

    @CrossOrigin注解底层通过Spring的拦截器功能往response里添加 Access-Control-Allow-Origin等响应头信息。
    response.setHeader(“Access-Control-Allow-Origin”, “*”);

  • 相关阅读:
    rk3588 mpp_log 不打印输出
    文理导航杂志文理导航杂志社文理导航编辑部2022年第12期目录
    【Vue】深究计算和侦听属性的原理
    贝锐花生壳内网穿透推出全新功能,远程业务连接更安全
    EasyPoi导入校验+导入自定义查询等校验
    设计模式-建造者模式
    后端跨域解决方案
    算法 | 基础 - [排序]
    小目标检测-FA-SSD
    Nginx学习(3)—— Nginx的应用
  • 原文地址:https://blog.csdn.net/qq_36881887/article/details/125457820