跨域访问相关


现在流行的趋势是前后端分离,牵扯到跨域访问问题的解决,下面说一下。


正文

什么是跨域请求,跨域的产生来源于现代浏览器所通用的‘同源策略’,所谓同源策略,是指只有在地址的:协议名、域名、端口名, 均一样的情况下,才允许访问相同的cookie、localStorage或是发送Ajax请求等等。若在不同源的情况下访问,就称为跨域。

浏览器出于安全考虑,并不是所有域名都可以直接访问。浏览器在发起任意的请求之前, 浏览器会判断目标的url是不是和当前网站是来自相同的域名,相同则一般认为是安全的, 不同则被认为是跨域,此种请求就是跨域请求,它默认是不可信、不安全的。 (当然,如果不是由浏览器发出的请求,那么自然不是浏览器的责任,比如ddos,就不属于跨域请求的范畴了)

同源策略分为以下两种:

  • DOM同源策略:禁止对不同源页面DOM进行操作。这里主要场景是iframe跨域的情况,不同域名的iframe是限制互相访问的。
  • XmlHttpRequest同源策略:禁止使用XHR对象向不同源的服务器地址发起HTTP请求。 只要协议、域名、端口有任何一个不同,都被当作是不同的域,之间的请求就是跨域操作。

情况一

一般如果前端只是纯粹的获取后端数据,后端只要允许跨域访问就可以了。 PHP设置header头:

header("Access-Control-Allow-Origin: *");

也可以设置为指定域名访问。

情况二

后端要求前端传递自定义header头信息。

后端示例:

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: jwt");

前端示例:

$.ajax({
    type: "GET",
    url: "http://test.host/190304/index.php",
    headers: {
        'jwt':'123'
    },
    success: function(data) {
        console.log(data);
    }
});

前端会有两次请求,第一次嗅探后端是否支持jwt这个自定义头信息,返回允许,第二次才带上jwt这个头信息去获取后端数据。

如果是JQuery,后端需要前端带上其他header信息,前端需要设置crossDomain为true,:

$.ajax({
    type: "GET",
    url: "http://test.host/190304/",
    crossDomain: true,
    success: function(data) {
        console.log(data);
    }
});

情况三

如果牵扯到认证,可以用JWT方式。JWT比较适合的场景是多个服务端用同一个JWT通信,可以简化认证的复杂性。 JWT发现的缺点有:有效期限制(过了这个时间就需要重新去获取JWT认证信息)、 跨域访问,如果是header带上JWT信息,每次都会有两次请求(第一次获取是否允许带这个JWT认证信息头, 第二次才是带上这个JWT认证信息头获取数据),比较浪费资源。

比较合理的方式是cookie带上JWT认证信息,这样就可以避免两次请求,但是如果是cookie方式认证, 那就完全没有必要用JWT了,用JWT只是多此一举,cookie中本来就可以设置加密的认证信息, 而且每次去后端访问都会更新cookie中的认证信息有效时长,也避免了JWT有效期限制的问题。

前后端分离后,后端要求cookie交互,后端需要设置:

header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Origin: http://ceshi.host");

Access-Control-Allow-Credentials设置为true后,Access-Control-Allow-Origin要写具体域名,否则不支持。

如果后端支持多个域名可跨域访问:

$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';  
  
$allow_origin = array(  
    'http://ceshi1.com',  
    'http://ceshi2.com'  
);  
  
if (in_array($origin, $allow_origin)) {  
    header('Access-Control-Allow-Origin:' .$origin);       
} 

前端如果是JQuery:

$.ajax({
    type: "GET",
    url: "http://test.host/190304/",
    xhrFields: {
        withCredentials: true
    },
    success: function(data) {
        console.log(data);
    }
});

withCredentials: true 携带跨域cookie

这样后端可以设置cookie,前端访问后端时也会把cookie带上。






参考资料

https://www.cnblogs.com/nuccch/p/7875189.html

https://blog.csdn.net/z69183787/article/details/78954325

https://blog.csdn.net/thc1987/article/details/54572272

https://blog.csdn.net/Zsigner/article/details/81159731

http://www.runoob.com/w3cnote/php-ajax-cross-border.html

HTTP访问控制(CORS) https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

Cross-Origin Resource Sharing协议介绍 https://www.cnblogs.com/shanyou/archive/2012/09/16/2687907.html

JWT https://blog.csdn.net/weixin_41153791/article/details/82291144

ajax() http://www.w3school.com.cn/jquery/ajax_ajax.asp

ajax() http://www.runoob.com/jquery/ajax-ajax.html


返回