• 跨域经验总结


    跨域踩坑经验总结(内涵:跨域知识科普)

    Published on: 2018-06-27

    跨域问题是我们非常常见的问题,尤其在跨系统页面间的调用经常会遇到,解决的方式在网上一搜一大把,这里整理出我遇到跨域问题解决的方式以及思路,如何安全的解决跨域调用请继续往下看。

    什么是跨域?

    什么是Cross-origin_resource_sharing? 跨域请求存在的原因:由于浏览器的同源策略,即属于不同域的页面之间不能相互访问各自的页面内容。

    跨域使用的场景?

    1. 域名不同
      • www.jiuyescm.comwww.jiuye.com即为不同的域名
    2. 二级域名相同,子域名不同
      • a.jiuyescm.comb.jiuyescm.com为子域不同
    3. 端口不同,协议不同
      • http://www.jiuyescm.comhttps://www.jiuyescm.com
      • www.jiuyescm.com:8888www.jiuyescm.com:8080

    解决跨域的方式?

    1. jsonp
      • 安全性差,已经不推荐
    2. CORS(W3C标准,跨域资源共享 - Cross-origin resource sharing)
      • 服务端设置,安全性高,推荐使用
    3. websocke
      • 特殊场景时使用,不属于常规跨域操作
    4. 代理服务(nginx)
      • 可作为服务端cors配置的一种方式,推荐使用

    前端、后端如何配合处理跨域?

    ps. 我们这里只介绍:CORS处理方式。

    跨域常见错误

    首先让我们看一下前端报出的跨域错误信息

    第一种:No 'Access-Control-Allow-Origin' header is present on the requested resource,并且The response had HTTP status code 404

    XMLHttpRequest cannot load http://b.domain.com, Response to preflinght request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a.domain.com' is therefore not allowed access. The Response had HTTP status code 404.
    

    ps.并且The response had HTTP status code 404

    问题原因:服务器端后台没有允许OPTIONS请求

    第二种:No 'Access-Control-Allow-Origin' header is present on the requested resource,并且The response had HTTP status code 405

    XMLHttpRequest cannot load http://b.domain.com, Response to preflinght request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a.domain.com' is therefore not allowed access. The Response had HTTP status code 405.
    

    ps.并且The response had HTTP status code 405

    问题原因:服务器端后台允许了OPTIONS请求,但是某些安全配置阻止了OPTIONS请求

    第三种:No 'Access-Control-Allow-Origin' header is present on the requested resource,并且The response had HTTP status code 200

    XMLHttpRequest cannot load http://b.domain.com, Response to preflinght request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a.domain.com' is therefore not allowed access.
    

    ps.并且The response had HTTP status code 200

    问题原因:服务器端后台允许了OPTIONS请求,并且OPTIONS请求没有被阻止,但是头部不匹配。

    第四种:heade contains multiple values '*,*',并且The response had HTTP status code 200

    XMLHttpRequestcannot load http://b.domain.com. The 'Access-Control-Allow-Origin' header contains multiple values'*, *', but only one is allowed. Origin 'http://a.domain.com' is therefore notallowed access.
    

    ps.并且The response had HTTP status code 200

    问题原因:设置多次Access-Control-Allow-Origin=*,可能是配置的人对CORS实现原理和机制不了解导致。

    突如其来的OPTIONS请求?

    有时你会发现明明请求的是POST、GET、PUT、DELETE,但是浏览器中看到的确实OPTION,,为什么会变成OPTION?

    原因:因为本次Ajax请求是“非简单请求”,所以请求前会发送一次预检请求(OPTIONS),这个操作由浏览器自己进行。如果服务器端后台接口没有允许OPTIONS请求,将会导致无法找到对应接口地址,因此需要服务端提供相应的信息到response header中,继续往下看。

    后端需要返回的Header有哪些?

    # 服务端允许访问的域名
    Access-Control-Allow-Origin=https://idss-uat.jiuyescm.com
    # 服务端允许访问Http Method
    Access-Control-Allow-Methods=GET, POST, PUT, DELETE, PATCH, OPTIONS
    # 服务端接受跨域带过来的Cookie,当为true时,origin必须是明确的域名不能使用*
    Access-Control-Allow-Credentials=true
    # Access-Control-Allow-Headers 表明它允许跨域请求包含content-type头,我们这里不设置,有需要的可以设置
    #Access-Control-Allow-Headers=Content-Type,Accept
    # 跨域请求中预检请求(Http Method为Option)的有效期,20天,单位秒
    Access-Control-Max-Age=1728000
    

    ps. 如果跨域需要携带cookie去请求,Access-Control-Allow-Credentials必须为true,但是需要注意当Access-Control-Allow-Credentials=true时,Access-Control-Allow-Origin就不能为” * “ ,必须是明确的域名,当然可以多个域名使用 “,” 分割

    前端如何配合发起请求?

    如果是浏览器直接访问跨域请求url,只要服务端返回 “Access-Control-Allow-X” 系列header在response中即可成功访问。

    如果是ajax发起的请求该如何处理?

    第一种:请求不需要携带cookie

    $.ajax({
        url : 'url',
        data : data,
        dataType: 'json',
        type : 'POST',
        crossDomain: true,
        contentType: "application/json",
        success: function (data) {
            var a=JSON.stringify(data);
            if(data.result==true){
              ...........
           }else{
           ...........
         }
        },
        error:function (data) {
            var a=JSON.stringify(data);
            alert(a);
        }
    });
    

    ps. 增加crossDomain=true

    第二种:请求需要携带cookie

    $.ajax({
        url : 'url',
        data : data,
        dataType: 'json',
        type : 'POST',
        xhrFields: {
            withCredentials: true
        },
        crossDomain: true,
        contentType: "application/json",
        success: function (data) {
            var a=JSON.stringify(data);
            if(data.result==true){
              ...........
           }else{
           ...........
         }
        },
        error:function (data) {
            var a=JSON.stringify(data);
            alert(a);
        }
    });
    

    ps. 增加crossDomain与xhr.withCredentials,发送Ajax时,Request header中便会带上 Cookie 信息。

    到这里你以为跨域的相关都介绍完毕了?太天真

    最后还有一个终极boss问题,是什么问题呢?

    上面的第二种携带cookie的跨域请求调用方式在IOS下可以正常工作,但是在Android下无法正常工作并且还报错,额。。。。。

    Ajax跨域请求跨平台兼容性问题

    问题原因:因为Android下的webview不兼容这个写法,使用标准的 beforeSend(XHR) 替换

    xhrFields: {
        withCredentials: true
    }
    

    ps. webview不兼容的写法,firefox下也不兼容

    标准的写法:

    $.ajax({
        type: "POST",
        url: "url",
        data:datatosend,
        dataType:"json",
        beforeSend: function(xhr) {
            xhr.withCredentials = true;
        }
        crossDomain:true,
        success: function (data) {
            var a=JSON.stringify(data);
            if(data.result==true){
              ...........
           }else{
           ...........
         }
        },
        error:function (data) {
            var a=JSON.stringify(data);
            alert(a);
        }
    });
    

    到这跨域的相关使用就介绍完毕,这次是真的结束了。Keep Real!

    转载: https://ningyu1.github.io/site/post/92-cors-ajax/

    浪漫家园,没事就来逛逛
  • 相关阅读:
    ural 1519 fomular 1 既插头DP学习笔记
    2016集训测试赛(十九)Problem C: 无聊的字符串
    2016集训测试赛(十九)Problem A: 24点大师
    2016集训测试赛(二十)Problem B: 字典树
    写一个addEventListener以及removeEventListener
    关于props的注意事项!
    swiper轮播始终居中active图片
    vue中登录模块的插件封装
    v-show
    v-if
  • 原文地址:https://www.cnblogs.com/lovezbs/p/13839508.html
Copyright © 2020-2023  润新知