为什么Postman调接口不会跨域而浏览器会

发表于:2021-1-05 10:15

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:独行侠梦    来源:CSDN

  为什么postman调接口不会跨域而浏览器会?
  都在说跨域,为什么postman能访问接口,而浏览器就不行呢?这里需要理解什么是跨域,跨域是指的当前资源访问其他资源时发起的http请求由于安全原因(由于同源策略,域名、协议。端口中只要有一个不同就不同源),浏览器限制了这些请求的正常访问,特别需要注意的是这些发生在浏览器中。而通过postman等工具调用接口时,只是简单的访问一个资源,并不存在资源的相互访问。
  知识预热
  ·回调函数
  这里就不细讲回调函数啦,相信各位都能理解,用一个案例来说一下。
  “服务器”和“客户端”初次相识,相谈甚欢,客户端希望服务器把一个叫json的东西给它,”服务器“:你先忙着,我弄好了发给你,把你电话号码(回调函数)给我。
  跨域中的预检请求即是指浏览器在真正发送请求前,会先发送一个Options请求嗅探,请求成功后才会发送真实的请求。
  问答三连:
  为什么需要发送预检请求?是因为触发了浏览器的安全校验。
  为什么请求会触发安全校验?因为当前请求是一个"复杂请求"。
  为什么我的请求是“复杂的”?见下面解释——
  ·复杂和简单请求
  简单请求:请求方法是GET/HEAD/POST,并且contentType为text/plain、application/x-www-form-urlencoded、multipart/form-data。
  不满足上述条件的视为复杂请求,开发中我们常触发这个条件大多因为我们的请求的contentType设置的是application/json导致的。
  简单请求如果设置了Authentication认证header也会让请求“升级”为复杂请求。
  理解spring提供的@CrossOrigin注解
  @CrossOrigin(maxAge = 3600,origins = "*")
  @CrossOrigin可以放在某个方法上,或者放在类上,这样对类中所有请求方法有效,指定能访问的域集合,即是设置Access-Control-Allow-Origin。
  maxAge 属性指定了预检请求的缓存时间,单位是秒。对应http的Access-Control-Max-Age属性。
  缓存的内容为:Access-Control-Allow-Methods和Access-Control-Allow-Headers 提供的信息。
  理解使用jsonp解决跨域问题
  上面简单介绍了回调函数,jsonp是如何解决跨域的呢?其实就是利用了一个特性,html页面中引入不同域的js是不会引发跨域的,下面的案例中,我引入了一个在线的query地址,并且在script标签的src写上了后端的接口地址,从前端的角度我们可以想象成只是简单请求一个js文件,js文件的内容是一个函数调用,刚好浏览器本地定义了这个函数,所以请求完毕,就会对这个函数发起调用,当然前后端的函数名需要一样,这就是我们说的回调函数的机制。
  前端
  <html>
  <body>
  <head>
  <script  src="http://libs.baidu.com/jquery/1.7.2/jquery.min.js"></script>
  </head>
  <h3 id="test">init...</h3>
  </body>
  <script type="text/javascript">
      //定义回调函数,相当于上述说的“电话号码”
   function myCallback(res){
      alert(JSON.stringify(res));
  }
  </script>
    <script src="http://localhost:9992/cors/infoWithCallBack"></script> 
  --------------------------------------------------------------------------------
  后端:
     /**
       * 返回 使用回调函数包裹的json
       * @return
       */
      @RequestMapping("/infoWithCallBack")
      public String info(){
          JSONObject map = new JSONObject();
          map.put("msg","请求成功!");
          map.put("code","0000");
          map.put("data","获取到后端数据!");
          String str = map.toString();
          return "myCallback(" + str + ")";
      }
  上面的例子在正常返回的json前面包裹了一个函数名,为的是能让浏览器执行,如果不采用jsonp的方式,而是后端设置Access-Control-Allow-Origin,则请求到的不是一个标准json,所以我们需要改造一下,兼容两种方式。
  <script type="text/javascript">
  $(function(){
  
  $.ajax({
  type:'POST'
  ,dataType:"jsonp"
  ,url:'http://localhost:9992/cors/info3'
  ,data:{}
  ,contentType:'application/json;charset=utf-8'
  //,jsonp:"callback" //指定回调函数的名字。一般不改这个,默认callback
  //,jsonpCallback:"myCallback"  //手动执行发送给服务器的callback参数名,否则由jquery自动帮我们生成,类似jQuery17207352806672191685_1544278219377
  ,success:function(data){
  debugger;    
  alert("ajax: "+JSON.stringify(data));
  }
  });
  
  }
  </script>
  --------------------------------------------------------------------------------
   /**
       * 3.兼容jsonp和普通json请求
       * @return
       */
      @RequestMapping("/info3")
      public String info3(@RequestParam(name="callback",required = false) String callBack){
          JSONObject map = new JSONObject();
          map.put("msg","请求成功!");
          map.put("code","0000");
          map.put("data","获取到后端数据!");
          String result = map.toString();
          if(!StringUtils.isEmpty(callBack)){
              //如果是json请求,则包裹上回调函数
              return callBack + "(" + result + ")";
          }
          return result;
      }
  其他遇到的问题
  Uncaught SyntaxError: Unexpected token :
  在解决跨域时,遇到这种错误,一般是前端没有设置回调函数,而后端返回了被回调函数包裹的json。
  info?callback=callback:1 Uncaught ReferenceError: callback is not defined
      at info?callback=callback:1

      本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号