美文网首页
跨域问题

跨域问题

作者: 蜂鸟飞不停 | 来源:发表于2020-01-13 12:59 被阅读0次

    前后端数据交互经常会碰到请求跨域,什么是跨域,以及有哪几种跨域方式,这是本文要探讨的内容。

    一、什么是跨域?

    广义上讲,跨域是指一个域下的文档或者脚本试图请求另一个域下的资源。例如:

    1)资源跳转:重定向、表单提交。
    2)资源嵌入:<link>、<script>、<img>、<frame>等dom标签,还有样式中background:url()、@font-face()等文件外链。
    3)脚本请求: js发起的ajax请求、dom和js对象的跨域操作等。

    通常我们说的跨域是狭义的,是由浏览器同源策略限制的一类请求场景。“同源策略/SOP(Same origin policy)”是一种约定,它是浏览器最核心也是最基础的安全功能,如果没有“同源策略”,浏览器很容易受到XSS,CSFR等攻击。所谓同源是指:

    协议+域名+端口 三者相同,即便两个不同域名指向同一个ip地址,也非同源。

    二 、常见跨域场景

    常见跨域场景

    特别说明两点:
    1) 如果是协议和端口造成的跨域问题,前台界面是无能为力的。
    2)跨域问题上,仅仅是通过URL的首部来识别而不会根据域名对应的ip地址是否相同来判断。URL的首部可以理解成协议,域名和端口必须匹配。

    三、跨域请求,请求完成了吗?

    跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。你可能会疑问明明通过表单的方式可以发起跨域请求,为什么 Ajax 就不会?因为归根结底,跨域是为了阻止用户读取到另一个域名下的内容,Ajax 可以获取响应,浏览器认为这不安全,所以拦截了响应。但是表单并不会获取新的内容,所以可以发起跨域请求。同时也说明了跨域并不能完全阻止 CSRF,因为请求毕竟是发出去了。

    四、跨域解决方案

    1) 通过jsonp跨域
    通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。
    利用 <script> 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。

    1.1)原生实现:

    <script>
        var script = document.createElement('script');
        script.type = 'text/javascript';
    
        // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
        script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
        document.head.appendChild(script);
    
        // 回调执行函数
        function handleCallback(res) {
            alert(JSON.stringify(res));
        }
     </script>
    服务端返回如下(返回时即执行全局函数):
    
    handleCallback({"status": true, "user": "admin"})
    

    1.2)jquery ajax实现:

    $.ajax({
        url: 'http://www.domain2.com:8080/login',
        type: 'get',
        dataType: 'jsonp',  // 请求方式为jsonp
        jsonpCallback: "handleCallback",    // 自定义回调函数名
        data: {}
    });
    

    1.3)vue.js实现:

    this.$http.jsonp('http://www.domain2.com:8080/login', {
        params: {},
        jsonp: 'handleCallback'
    }).then((res) => {
        console.log(res); 
    })
    

    1.4) 后端node.js代码示例:

    var querystring = require('querystring');
    var http = require('http');
    var server = http.createServer();
    
    server.on('request', function(req, res) {
        var params = qs.parse(req.url.split('?')[1]);
        var fn = params.callback;
    
        // jsonp返回设置
        res.writeHead(200, { 'Content-Type': 'text/javascript' });
        res.write(fn + '(' + JSON.stringify(params) + ')');
    
        res.end();
    });
    
    server.listen('8080');
    console.log('Server is running at port 8080...');
    

    1.5) JSONP优缺点:
    JSONP优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持get方法具有局限性,不安全可能会遭受XSS攻击。
    2)跨域资源共享(CORS)

    跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法,浏览器必须首先使用 HTTP 的 OPTIONS 方法 用于获取目的资源所支持的通信选项。客户端可以对特定的 URL 使用 OPTIONS 方法,也可以对整站(通过将 URL 设置为“*”)使用该方法。") 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

    五、总结

    CORS支持所有类型的HTTP请求,是跨域HTTP请求的根本解决方案
    JSONP只支持GET请求,JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
    不管是Node中间件代理还是nginx反向代理,主要是通过同源策略对服务器不加限制。
    日常工作中,用得比较多的跨域方案是cors和nginx反向代理。

    相关文章

      网友评论

          本文标题:跨域问题

          本文链接:https://www.haomeiwen.com/subject/vpcunctx.html