`
javaEEdevelop
  • 浏览: 876248 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

JavaScript 跨域访问的问题和解决过程(转)

 
阅读更多

分享一下最近用jQuery跨域请求的经历, 

希望能给大家一些关于这个方案的概念和资料。

该部分包括客户端和服务器端,(如果服务器不在自己手上,那么还是考虑通过自己的服务器转发请求吧)

 

1.原本的代码很简单。。如果是同域名什么问题都没有 (有兴趣的朋友可以尝试在自己的服务器上运行以下代码)

复制代码
           $.ajax({
                url: "http://www.google.com/", //不同域名,而且google 没有允许第三方提交所以会出错
                cache: false,
                //data: params,
                dataType: 'json',
                success: function (data) {
                    console.log(data);
                },
                error: function (e) {
                    alert(e.statusText);
                }
            })
复制代码

嗯,我的默认浏览器是Chrome, 上去一跑。。。当然不能用。。。什么都还没做呢,就想做跨域访问这么危险的事情

下面是Chrome给出的错误提示 

 

2.在服务器端做点手脚,

                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); // 可以设置为详细的地址


3. 好了现在Chrome中的Get已经可以运行了,依葫芦画瓢开发了Post方法。。。。发现Post不能用。。。。- -# 真是不顺利啊

在Fiddler中发现客户端提交的是OPTIONS的请求。。。。恩。。。。。那就加一段逻辑处理OPTIONS

复制代码
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); // 可以设置为详细的地址

                if (HttpContext.Current.Request.HttpMethod == "OPTIONS") // 加点逻辑
                {
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept,X-Requested-With");
                    HttpContext.Current.Response.End();
                }
 
复制代码

实际运行中有两次请求 第一次是OPTIONS 第二次才是POST

 

4.还有问题。。。。忽然发现在IE8和IE9中无法运行,而在其他的浏览器中都正常(opera未测试,google说这个浏览器也有问题。不过这东西比较小众)

使用Fiddler发现 这个动作根本没有被提交到服务器端。。。。

经常Google以后发现。。。。IE8以上的版本跨域提交需要使用XDomainRequest 对象。。。。(IE 为什么每次你都这么另类!,jQuery你为什么不兼容ie8和ie9的跨域提交功能。。加点代码很麻烦么!!!)

复制代码
 var xdr = new XDomainRequest();
        xdr.onload = function (e) {
            var data = $.parseJSON(xdr.responseText);
            if (data == null || typeof (data) == 'undefined') {
                data = $.parseJSON(data.firstChild.textContent);
            }
            //success
        };
        xdr.onerror = function (e) {
            //error
        }

        xdr.open("GET", url);
        xdr.send();
复制代码

关于 XDomainRequest 请在这里查看详细,http://msdn.microsoft.com/en-us/library/cc288060(VS.85).aspx

 

5.恩 get功能在ie中也可以了。。。不错不错, POST还不行。。。莫非又是IE的问题?? 这。。怎么每个功能都这么多问题?

奇怪的是Fiddler中显示IE8 中POST请求确实发出去了啊。。。怎么回事??

把问题分解来看,吧fiddler获取的http request raw数据拿出来 单独提交试试。。。也不行?! 服务器返回415。。。 看来好像不是ie的问题。(这次冤枉了它了)

仔细排查,发现缺少Content-Type(Content-Type其实不是必须的,参考RFC)

这坑爹的WCF 3.5啊, 不传Content Type就给我报415异常  (WCF 4.0已经解决这个问题,3.5解决起来很麻烦,我一怒之下用了普通的ashx来处理)

.....嗯。。。少什么我加什么。。。 what?!!! XDomainRequest 不能随便设置header,    

var xdr=new XDomainRequest ();
xdr.contentType="application/json"; //异常。。。。。。。
xdr.contentType = "text/plain";  //这是唯一可以设置的值。。。。MS。。。我要json不要这个。。。。

好吧javascript这边设置失败了。。只能去服务器动手脚。。。想死的心都有了。。。。做点功能怎么这么麻烦。。。

到此为止,总算告一个段落了。。。

 

附录1

用来解决跨域问题的,服务器端代码

复制代码
    public class Global : System.Web.HttpApplication
    {
        protected void Application_BeginRequest(object sender, EventArgs e)
        {
            if (HttpContext.Current != null && HttpContext.Current.Response != null)
            {
                HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*"); // take care

                if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
                {
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
                    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Accept,X-Requested-With");
                    HttpContext.Current.Response.End();
                }
            }
        }

    }
复制代码

服务器也可以通过放置crossdomain.xml在根目录下指定该逻辑,参考http://www.weibo.com/crossdomain.xml 

 

附录2 用来解决客户端问题的参考代码(代码比较潦草,不过重要的是逻辑)

View Code
复制代码
function cloverGet(url, params, isRenderLoading, callback) {
    if ($.browser.msie && parseInt($.browser.version, 10) >= 8 && window.XDomainRequest) {
        var xdr = new XDomainRequest();

        xdr.onload = function (e) {
            var data = $.parseJSON(xdr.responseText);
            if (data == null || typeof (data) == 'undefined') {
                data = $.parseJSON(data.firstChild.textContent);
            }
            //需要手动处理json数据
        };
        xdr.onerror = function (e) {
          
        }
        xdr.open("GET", url);
        xdr.send();
    }
    else {
        $.ajax({
            url: url,
            cache: false,
            data: params,
            dataType: 'json',
            success: function (data) {
               
            },
            error: function (e) {
                
            },
            complete: function (e) {
               
            },
            beforeSend: function (xhr) {
              
            }
        });



    }
}
function cloverPost(url, params, callback) {

    if ($.browser.msie && parseInt($.browser.version, 10) >= 8 && window.XDomainRequest) {
        var xdr = new XDomainRequest();
        xdr.contentType = "text/plain";
        xdr.onload = function () {
            var data = $.parseJSON(xdr.responseText);
            if (data == null || typeof (data) == 'undefined') {
                data = $.parseJSON(data.firstChild.textContent);
            }
            //需要手动格式化
        };
        xdr.onerror = function (e) {

        }
        xdr.open("POST", url);
        xdr.send(params); //这里的数据是 a=1&b=2这样的

    }
    else {
        $.ajax({
            type: "POST",
            url: url,
            data: params,
            // dataType: "json",  //有的时候jsonp也是一个选择
            crossDomain: true,
            success: function (data) {

            },
            error: function (e) {
                 
            },
            complete: function (e) {
                 
            },
            beforeSend: function (xhr) {
                 
            }
        });
    }
}
复制代码

 

 

  • get和post都行了。。。还有文件上传呢。。。这样的POST是不能传文件的。。 (考虑用第三方方案或者不要直接提交)
  • 善用工具 例如Fiddler 还有javascript/HTML调试工具 (我个人觉得Chrome和FF的调试器比较好用)似乎不少人还习惯用alert调试。。。。
  •  IE和safari 跨域iframe有问题, 记得设置header,例如: Response.Headers["p3p"] = "CP=IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT";
  • 有兴趣的朋友可以了解一下XSS和CSRF,这可是网站的一大安全问题
  • 分解问题是排查问题的一个很好的办法
  • 更多的时候,使用同域名的代理服务器是很好的解决方案 (也是唯一的解决方案,如果浏览器直接调用第三方有权限问题的话)

 

本人水平有限,如果有所遗漏和谬误,请各位朋友指正,希望一起讨论学习和进步

原址(http://www.cnblogs.com/PurpleTide/archive/2011/11/06/2238293.html)

分享到:
评论

相关推荐

    解决ajax不能访问本地文件问题(利用js跨域原理)

    尽管JSONP和本文中的方法在某些场景下有效,但在实际开发中,更推荐使用CORS,因为它提供了更安全、更可控的跨域访问方式。同时,对于无服务器的前端项目,也可以考虑使用Web Workers或Service Worker等现代Web技术...

    Ajax跨域访问解决方案

    **Ajax跨域访问解决方案** 在Web开发中,Ajax(Asynchronous JavaScript and XML)技术被广泛用于实现页面的异步更新,提升用户体验。然而,由于浏览器的同源策略限制,Ajax请求只能向同源(协议、域名和端口相同)...

    javascript跨域访问的方法.pdf

    JavaScript跨域访问是Web开发中的常见挑战,由于浏览器的安全策略——同源策略,JavaScript通常只能访问与当前页面同源(协议、域名、端口都相同)的资源。然而,为了实现不同源之间的通信,开发者可以采取多种方法...

    解决JS跨域访问IFrame的解决方案

    综上所述,解决JS跨域访问IFrame的问题,需要根据实际需求和环境选择合适的解决方案,结合服务器端的支持和客户端的技术手段,确保跨域通信的安全和高效。在开发过程中,应充分理解同源策略的限制,熟练掌握跨域通信...

    MVC中跨域解决方案

    总结来说,MVC中处理跨域问题主要依赖于CORS机制,通过配置中间件、过滤器或Web.config文件来允许特定的源进行跨域访问。同时,也可以考虑JSONP、后端代理等其他解决方案。在实际项目中,应根据安全性和需求选择合适...

    JavaScript跨域总结与解决办法

    ### JavaScript跨域总结与解决办法 #### 跨域的基本概念 跨域问题源自于浏览器的安全策略之一——**同源策略**。同源策略是浏览器为了防止恶意网站通过脚本访问其他网站的数据而采取的一种安全措施。它规定了一个...

    链接修改及跨域访问的问题

    在IT领域,尤其是在Web开发中,跨域访问是一个常见的问题,因为浏览器的同源策略(Same-Origin Policy)限制了JavaScript从一个源获取资源到另一个源的能力。为了在不同软件系统间实现跨域通信,开发者需要采取一些...

    Geoserver跨域问题解决方案

    总的来说,解决Geoserver跨域问题需要理解浏览器的同源策略和CORS机制,并正确配置相应的库和过滤器。通过这个过程,我们可以为不同的客户端提供安全、可靠的跨域数据访问,从而实现更灵活的GIS应用。

    js_跨域访问[参照].pdf

    总的来说,解决JavaScript跨域问题通常需要结合客户端和服务器端的技术,根据实际情况选择合适的策略。对于开发过程中遇到跨域问题的场景,理解这些解决方案并灵活运用是非常重要的,以确保不同源之间能够安全、有效...

    vue-axios + vue3-axios Axiso解决跨域访问完整源码

    在 Vue 应用中,跨域访问是一个常见的问题。由于浏览器的安全策略,不同源(Origin)之间的通信会被阻止,这就是所谓的“同源策略”。为了绕过这一限制,我们需要使用 CORS(Cross-Origin Resource Sharing,跨源...

    js 跨域解决方案

    本文将深入探讨JavaScript跨域问题及其解决方案,以帮助开发者理解和应对这一问题。 首先,了解同源策略是解决问题的关键。同源策略是浏览器为了保障用户数据安全而实施的一种机制,它禁止了一个源的文档或脚本获取...

    解决跨域访问:vue-axios + vue3-axios Axiso解决跨域访问完整源码分享

    在 Vue 应用中,跨域访问是一个常见的问题。由于浏览器的安全策略,不同源(Origin)之间的通信会被阻止,这就是所谓的“同源策略”。为了绕过这一限制,我们需要使用 CORS(Cross-Origin Resource Sharing,跨源...

    跨域访问演示环境和代码

    在跨域访问的过程中,安全性是首要考虑的问题,因此需要谨慎处理,避免恶意请求。 通过"跨域访问演示环境和代码"的实践,开发者能够深入理解这两个跨域解决方案的工作原理,并学会如何在实际项目中应用。无论是...

    解决ajax跨域请求问题

    同时,开发过程中要注意安全问题,避免因为放开跨域限制而导致敏感信息泄露。 为了更好地理解和应用这些知识,可以参考以下资源: - 博文链接:https://x125858805.iteye.com/blog/2215862 - 在压缩包文件"kuayu2...

    jquery 跨域访问问题解决方法(笔记)

    这篇文章主要讲述了解决jQuery跨域访问问题的方法,并且通过一个具体的案例来说明了问题的解决过程。 首先,让我们明确什么是跨域访问问题。跨域访问指的是当一个网页试图从不同域名的服务器请求资源时,由于浏览器...

    arcgis js跨域解决策略

    然而,在实际开发过程中,由于浏览器的同源策略限制,当我们在不同域名下尝试访问ArcGIS服务时,会遇到跨域问题。本文档将详细介绍如何在.NET或Java环境下解决这一问题。 跨域问题源于浏览器的安全策略,旨在防止...

    解决Vue调用springboot接口403跨域问题

    然而,跨域资源共享(CORS)问题常常会成为前后端整合过程中的一个难题。在本文中,我们将详细探讨如何解决Vue调用Spring Boot接口时遇到的403跨域问题。 ### CORS问题简介 跨域资源共享(CORS)是一种安全机制,...

    【JavaScript源代码】解决vue $http的get和post请求跨域问题.docx

    当设置好代理后,虽然在浏览器的网络面板中,你可能会看到请求仍然显示为`http://localhost:8080/api/...`,但实际上,代理已经将请求转发到了`http://localhost:9080/...`,实现了跨域访问。 总结,解决Vue.js中$...

    getJSON解决 跨域问题例子

    以上就是使用getJSON解决跨域问题的基本方法,以及相关的JSONP和CORS机制。在实际开发中,我们需要根据项目需求和服务器支持情况选择合适的跨域策略。同时,对于“请求测试”这个文件名,可能是用于测试不同跨域解决...

    JavaScript跨域处理

    JavaScript跨域处理是Web开发中的一个关键概念,由于浏览器的安全策略,JavaScript通常被限制在同一源策略下运行,这意味着脚本只能访问与加载它的页面来自同一域名的资源。然而,在实际应用中,为了实现数据交互、...

Global site tag (gtag.js) - Google Analytics