跨域问题解决方案(HttpClient安全跨域 & jsonp跨域)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了跨域问题解决方案(HttpClient安全跨域 & jsonp跨域)相关的知识,希望对你有一定的参考价值。

1 错误场景                                         

       今天要把项目部署到外网的时候,出现了这样的问题, 我把两个项目放到自己本机的tomcat下, 进行代码调试, 运行

都没有问题的, 一旦把我需要调用接口的项目B放到其他的服务器上, 就会报错, 无法通过Ajax调用springMVC的接口,

这是什么原因呢?

      当我使用json ajax post请求传递数据的时候在web端出错:XMLHttpRequest cannot loadhttp://ip:8082/security/auth/outside.do. Origin http://ip:8080 is not allowed by Access-Control-Allow-Origin.

 

2 初识jsonp                               

      经过在网上查找, 网上大多数说是跨域问题. 解决跨域问题据说是jsonp, 百度了一篇文章, 不管三七二十一就一下

子把ajax传递的数据类型dataType 改成为jsonp, 并使用get方式, 单纯的认为, json和jsonp没啥区别, 运行, 报错, 如

下图所示:

技术分享

 

      没有了上述的 is not allowed ....的错误, 变成了只剩下500的错误, 说明jsonp起了些作用, 我的bug的问题就是在于网上说的"跨域" 。而究竟什么是跨域呢?

 

3 什么是跨域?什么是不跨域?           

      上没有过多的去测试,一句话:同一个ip、同一个网络协议、同一个端口,三者都满足就是同一个域,否则就是

跨域问题了。而为什么开发者最初不直接定为一切可跨域的呢?默认的为什么都是不可跨域呢?这就涉及到了同源策

略,为了系统的安全,由Netscape提出一个著名的安全策略。现在所有支持JavaScript的浏览器都会使用这个策略。

所谓同源是,域名,协议,端口相同。当我们在浏览器中打开百度和谷歌两个网站时,百度浏览器在执行一个脚本的

时候会检查这个脚本属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行,如果没有同源策略,那

随便的向百度中注入一个js脚本,弹个恶意广告,通过js窃取信息,这就很不安全了。

 

4 跨域问题如何解决?jsonp为什么能解决跨域问题?和json有什么区别?

      关于解决跨域问题,有多种解决方案,解决方案如下。

 

      4.1 方案一

      ajax请求地址改为自己系统的后台地址,之后在自己的后台用HttpClient请求url。封装好的跨域请求url工具类

代码如下所示。

 

 
<span style="font-size:18px;">@SuppressWarnings("all")  
public final class UrlUtil {  
  
    private static HttpClient httpClient = new HttpClient();  
  
    /** 
     * @Title: getDataFromURL 
     * @Description: 根据URL跨域获取输出结果,支持http 
     * @param strURL 
     *            要访问的URL地址 
     * @param param 
     *            参数 
     * @return 结果字符串 
     * @throws Exception 
     */  
    public static String getDataFromURL(String strURL, Map<String, String> param) throws Exception {  
        URL url = new URL(strURL);  
        URLConnection conn = url.openConnection();  
        conn.setDoOutput(true);  
  
        OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());  
        final StringBuilder sb = new StringBuilder(param.size() << 4); // 4次方  
        final Set<String> keys = param.keySet();  
        for (final String key : keys) {  
            final String value = param.get(key);  
            sb.append(key); // 不能包含特殊字符  
            sb.append(‘=‘);  
            sb.append(value);  
            sb.append(‘&‘);  
        }  
        // 将最后的 ‘&‘ 去掉  
        sb.deleteCharAt(sb.length() - 1);  
        writer.write(sb.toString());  
        writer.flush();  
        writer.close();  
  
        InputStreamReader reder = new InputStreamReader(conn.getInputStream(), "utf-8");  
        BufferedReader breader = new BufferedReader(reder);  
        // BufferedWriter w = new BufferedWriter(new FileWriter("d:/1.txt"));  
        String content = null;  
        String result = null;  
        while ((content = breader.readLine()) != null) {  
            result += content;  
        }  
  
        return result;  
    }  
  
    /** 
     * @Title: postMethod 
     * @Description: 根据URL跨域获取输出结果,支持https 
     * @param url 
     *            要访问的URL地址(http://www.xxx.com?) 
     * @param urlParm 
     *            参数(id=1212&pwd=2332) 
     * @return 结果字符串 
     */  
    public static String postMethod(String url, String urlParm) {  
        if (null == url || "".equals(url)) {  
            // url = "http://www.baidu.com";  
            return null;  
        }  
        PostMethod post = new PostMethod(url); // new UTF8PostMethod(url);  
        if (null != urlParm && !"".equals(urlParm)) {  
            String[] arr = urlParm.split("&");  
            NameValuePair[] data = new NameValuePair[arr.length];  
            for (int i = 0; i < arr.length; i++) {  
                String name = arr[i].substring(0, arr[i].lastIndexOf("="));  
                String value = arr[i].substring(arr[i].lastIndexOf("=") + 1);  
                data[i] = new NameValuePair(name, value);  
            }  
            post.setRequestBody(data);  
        }  
        int statusCode = 0;  
        String pageContent = "";  
        try {  
            statusCode = httpClient.executeMethod(post);  
            if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {  
                pageContent = post.getResponseBodyAsString();  
                return pageContent;  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
            return null;  
        } finally {  
            post.releaseConnection();  
        }  
        return null;  
    }  
  
    public static String doPost(String url, String json) throws Exception {  
        PostMethod postMethod = new PostMethod(url);  
        StringRequestEntity requestEntity = new StringRequestEntity(json, "application/json", "UTF-8");  
        postMethod.setRequestEntity(requestEntity);  
        /* 发送请求,并获取响应对象 */  
        int statusCode = httpClient.executeMethod(postMethod);  
        String result = null;  
        if (statusCode == HttpStatus.SC_OK) {  
            result = postMethod.getResponseBodyAsString();  
        } else {  
            System.out.println("Method failed: " + postMethod.getStatusLine());  
        }  
        return result;  
    }  
  
    public static String post(String url, Map<String, String> params) {  
        DefaultHttpClient httpclient = new DefaultHttpClient();  
        String body = null;  
        HttpPost post = postForm(url, params);  
        body = invoke(httpclient, post);  
        httpclient.getConnectionManager().shutdown();  
        return body;  
    }  
  
    private static HttpPost postForm(String url, Map<String, String> params) {  
        HttpPost httpost = new HttpPost(url);  
        List<BasicNameValuePair> nvps = new ArrayList<BasicNameValuePair>();  
        Set<String> keySet = params.keySet();  
        for (String key : keySet) {  
            BasicNameValuePair basicNameValuePair = new BasicNameValuePair(key, params.get(key));  
            nvps.add(basicNameValuePair);  
        }  
        try {  
            httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));  
        } catch (UnsupportedEncodingException e) {  
            e.printStackTrace();  
        }  
        return httpost;  
    }  
  
    private static String invoke(DefaultHttpClient httpclient, HttpUriRequest httpost) {  
        HttpResponse response = sendRequest(httpclient, httpost);  
        String body = paseResponse(response);  
        return body;  
    }  
  
    private static HttpResponse sendRequest(DefaultHttpClient httpclient, HttpUriRequest httpost) {  
        HttpResponse response = null;  
        try {  
            response = httpclient.execute(httpost);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return response;  
    }  
  
    private static String paseResponse(HttpResponse response) {  
        HttpEntity entity = response.getEntity();  
        String body = null;  
        try {  
            body = EntityUtils.toString(entity);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
        return body;  
    }  
  
    public static void main(String[] args) throws Exception {  
        String url = "http://ip:8082/security/auth/outside.do";  
        Map<String, String> map = new HashMap<String, String>();  
        map.put("loginName", "root");  
        map.put("code", "vms2.0");  
        String msg = post(url, map);  
        JSONArray jary = JsonUtil.Json2JSONArray(msg);  
        for (int i = 0; i < jary.length(); i++) {  
            JSONObject obj = jary.getJSONObject(i);  
            System.out.println(obj);  
//          System.out.print(obj.getString("classid"));  
//          System.out.print("\t"+obj.getString("classname"));  
//          System.out.println("\t"+obj.getString("sonclass"));  
        }  
//      System.out.println(jary);  
    }  
}

 


       当然要导入httpclient-4.3.1.jar包到自己的项目中哦。这样把请求的参数内容放到map中,通过HttpClent来实现跨域请求。

       4.2 解决方案二

       两个系统之间的数据传递是通过ajax post请求,传递json的方式来完成,我们在这里可以使用jsonp的方式,但

是json和jsonp截然不同。首先说说神马是json,再说神马是jsonp。

json

       全拼(javascript Object Notation)轻量级的数据交换格式,易于机器解析和生成。基于javaScript

Programming Language,StandardECMA Edition December1999的一个子集。json完全独立于语言的文本格

式,但是也使用类似于C语言家族的习惯(include c c++ c# Java javaScript perl Python)等,这些特性使得json

成为理想的数据交换语言。格式为key,value格式,具体就不赘述了。

jsonp

       jsonp全拼是(json with Padding)是json的一种使用模式,padding意思为填料,垫料,填充,填补。json可

以说是名词,而jsonp是动宾短语,两者有联系,但是有本质的区别,就像米饭和把米饭填充到碗里一样,那米饭和

米饭填是一样的么,我们自然明了了。


以上是关于跨域问题解决方案(HttpClient安全跨域 & jsonp跨域)的主要内容,如果未能解决你的问题,请参考以下文章

解决ajax跨域问题

使用Httpclient 完美解决服务端跨域问题

juery的跨域请求2

JSONP和HttpClient的区别

Angular 5,httpclient,跨域请求被阻止

用jQuery实现jsonp跨域