jsonp无X-Requested-With 及其深扒

    事件背景交代

    事情的起因是:A和B站都得调A站的接口,然后前端把请求写成jsonp的,又因为js是在CDN上,A和B是公用相同的js。然后就出现了A站调接口出现前端无法解析的问题,B站调A站接口却正常。出现无法解析的问题是因为callback被包了两层,即callback(callback("result"))

    问题分析

    既然是返回的内容出现了问题,那就是后端的代码问题,二话不说看代码。看了好长时间,果然拦截器的代码写的有问题:有两个拦截器,

一个是调用接口类所在包的拦截器(局域拦截器),针对这个包下面的每一个请求判断是否jsonp,是jsonp就自动给返回内容包一层callback;

另外一个是全局的拦截器中,对每个请求都进行了判断,如果请求中带有callback参数且请求类型是ajax,那就自动给返回内容包上一层callback。


显然,A站调A站自己的接口,是符合两个拦截器的条件的,所以,返回内容被callback包了两次,出现了返回内容无法被解析的问题;而B站调A站接口却是只符合局域拦截器的,所以返回内容是正常的,可以被解析。

    问题总结

    这里总结一下,其实前端和后端代码都有问题:

         前端代码有问题是A站调A站,怎么用jsonp呢(从技术的角度是可以实现的,但是,逻辑上是错误的),只需要普通的ajax即可;

         后端的代码有问题是在判断请求是否jsonp的同时又判断请求类型是否ajax,这两个条件不可能同时满足的,因为jsonp不是ajax,虽然我们是通过jquery的ajax设置dataType为jsonp来实现jsonp的,但是,jsonp是普通的请求。


    问题深扒

    为什么jsonp是普通请求而不是ajax呢?这里说下,ajax请求是肯定带有X-Requested-With请求头的,而普通的请求是不会有X-Requested-With请求头,所以我们一般判断是ajax还是普通请求是通过这个X-Requested-With头来判断的。


     正好有时间就深扒了下这个问题。因为浏览器受到同源策略限制,A源(域名)下的资源,只可以访问A源的接口,如果不做处理的话,A源访问B源的接口,会出现也就是我们所常说的跨域问题了。                                                                                                                                           


    处理跨域问题,有哪几种方案呢?一般来说,有三个方案

    jsonp

         jsonp是根据img和script等是通过src属性来下载资源的,而src的方式是不受跨域的影响的。jquery的jsonp是通过动态生成script标签带上参数和callback去向服务器请求资源,然后请求返回后,根据callback调用指定的方法,再把生成的script标签给删除。


    两次请求的方式

         第一次调自己的服务端的接口,第二次在服务端调“其他源”的接口(跨域是针对浏览器的,对服务器来说是没有什么跨域不跨域的)

    CORS

        假如A站要调B站的接口,在不做处理之前肯定是http 403的,要用CORS的方式,需要在B站写个过滤器/拦截器/甚至AOP,拦截请求,在每个请求中加上 response.setHeader("Access-Control-Allow-Origin", "*"); 表示该资源可以被任意的外域访问




参考:

http://www.cnblogs.com/digdeep/p/4170059.html

http://blog.csdn.net/puma_dong/article/details/51395976

posted @ 2017-07-19 21:59  Bug开发攻城狮  阅读(202)  评论(0编辑  收藏  举报