AJAX跨域的简单总结

JS不容许跨域,不是指浏览器压根不发起请求,只是浏览器拿到响应后,可能对当前域不可见。

测试场景

在开源中国oschina主页的console下发起对csdn主页的ajax请求

$.ajax("http://www.csdn.net/",{
                success:function(data){
                    console.log(data)
                }
            });

控制台打出下面的错误日志:

XMLHttpRequest cannot load http://www.csdn.net/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.oschina.net' is therefore not allowed access.

翻译过来意思是:“http响应头里没有发现“Access-Control-Allow-Origin”,因此不可操作”。

这里产生一个思考:如果响应头里面包含Access-Control-Allow-Origin是不是就不存在跨域问题了?是的,但是你得联系csdn的人去给你改配置或者改代码...... 

几种常见的跨域方法

  • 第一种:代理,即后台跨域,然后提供给本域JS (推荐使用,因为大多数的情况下目标域的http服务不可能为了你一个跨域需求而做任何代码和配置上的更改

比如上面的场景,我们在开源中国oschina的后台,创建一个Http代理服务,通过Http客户端去调用csdn,然后将服务提供给oschina本域的JS访问。以下是后台Java的实现方法方法:

    /**
     * 后台跨域访问csdn首页
     */
    @RequestMapping("/cross-domain/csnd/firstpage")
    public String index(HttpServletResponse response) throws IOException {
        URL url = new URL("http://www.csdn.net/");
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setDoInput(true);
        con.setDoOutput(true);
        con.setUseCaches(false);
        con.setRequestMethod("GET");
        con.setRequestProperty("Connection", "Keep-Alive");
        con.setRequestProperty("Charset", "UTF-8");
        BufferedReader br = new BufferedReader(new InputStreamReader(
                con.getInputStream()));
        StringBuffer stringBuffer = new StringBuffer();
        String str = "";
        while ((str = br.readLine()) != null) {
            stringBuffer.append(str);
        }
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out=response.getWriter();
        out.print(stringBuffer.toString());
        out.flush();
        out.close();
    }

然后我们更换url,再发起请求即可:

$.ajax("http://www.oschina.net/cross-domain/csnd/firstpage",{
                success:function(data){
                    console.log(data)
                }
            });

  •  第二种:利用jsonp (不是很推荐使用,因为除了JS,目标域的返回代码也得做特殊处理。可能适用于同一个公司内开发,因为别人会支持你做修改,当然如果前后台代码都是你在写那就好说了)

     关于jsonp跨域的原理网上有一大堆方法和实例,这里仅以jquery的jsonp跨域来说明前后台到底都需要哪些特殊处理:

     Js端:

$.ajax("http://www.csdn.net/",{
            dataType:"jsonp",//设置jsonp类型
            jsonp: "successCallback",//这个需要让后台知道,默认为callback
            success:function(data){
                console.log(data)
            }
        });

      csdn服务端,再返回数据时需要将结果包装一下,如下:

String result="csdn有点大而虚:问个问题基本就沉了,但下载频道还行,我还冲了10块钱";
String prefix=request.getParameter("successCallback"); //从前台取successCallback得值
return prefix + "(" + result + ")"; //在返回的result数据前后特殊处理

    

  •  第三种:设置目标域的http响应头 'Access-Control-Allow-Origin' 容许当前域  (不推荐)

     此方法使得任何一方的代码都不做任何特殊处理,但一般为了安全,使用的不多,  即使使用的话一般也是在相同主域的不同子域间使用,比如a.baidu.com容许b.baidu.com跨域。

 

 

你可能感兴趣的:(AJAX跨域)