导航

AJAX跨域问题

Posted on 2015-12-25 16:02  寒宵飞飞  阅读(326)  评论(0编辑  收藏  举报

        最近遇到一个项目,你的JSP网页和服务器提供的服务不在一个域中,但是需要通过AJAX方式来跨域调用服务器的服务,例如

你的JSP页面:http://192.168.6.26:7001/First_Web/TestXML.jsp

服务器的服务地址:http://10.8.2.60:9082/PGIS_S_Map/XMLPort

        众所周知,AJAX是不能跨域的,因为跨域访问会涉及很严重的安全问题,不仅是AJAX技术,采用任何方式(例如表单post)来跨域访问都会涉及严重的问题。例如你在你的网站中通过AJAX去跨域修改网站B后台服务器的数据,这里面当然会涉及到权限问题,如果权限被绕过(例如通过CSRF,XSS等技术窃取网站B的cookies),跨域访问又被允许的情况下,网站B的后台数据就会被窃取和破坏。

       目前AJAX跨域解决方式主要有以下几种:

 

一、主域名相同,子域名不同

     例如:http://www.aa.com/和book.aa.com,主域名都是aa.com,

     解决方式:此时可以通过设置document.domain方式解决,具体可以参考http://blog.sina.com.cn/s/blog_62449fcf0100p3bp.html


二、域名完全不同

     例如我在项目中遇到的就是这种情况,这种情况又可以分为两类:

     1)客户端只需要通过get方式来跨域请求服务端的服务

     解决方式:jQuery+jsonp

       具体可参考:http://www.biaodianfu.com/json-jsonp.html

     2)客户端需要通过POST和GET方式来跨域请求服务端的服务

     解决方式:中转代理方式,客户端在本地建立一个Servlet和JSP做中转代理,先将请求发送到代理,代理将请求转发到服务器,并接收反馈结果,并将结果返回到客户端

       下面介绍代理方式:

1)客户端TestXML.jsp,其中txtInput用于输入请求的xml数据,txtOutput用于输出返回的XML数据,客户端将请求的XML数据和服务器的服务地址一致发送给代理ClientServlet

<%@ page language="java" import="java.util.*" pageEncoding="GB2312"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
  <title>test XML</title>
     <SCRIPT LANGUAGE="JavaScript"> 
     
var XMLHttpReq;   
    
//创建XMLHttpRequest对象,通过XMLHttpRequest请求服务器端的数据        
    function createXMLHttpRequest() {                
        
if(window.XMLHttpRequest) { //Mozilla 浏览器   
            XMLHttpReq = new XMLHttpRequest();   
        }   
        
else if (window.ActiveXObject) { // IE浏览器   
            try {   
                XMLHttpReq 
= new ActiveXObject("Msxml2.XMLHTTP");   
            }
catch (e) {   
                
try {   
                    XMLHttpReq 
= new ActiveXObject("Microsoft.XMLHTTP");   
                } 
catch (e) {}   
            }   
        }   
    }   
    
//发送请求函数到服务器,这里服务器的处理程序为servlet程序   
    function sendRequest() 
    {   
        document.getElementById(
"txtOutput").innerHTML ="正在查询,请您稍等......";    
        createXMLHttpRequest();   
        
        
var xmldata = "xml="+document.getElementById("txtInput").value;
        
var urldata = "url=http://10.8.2.60:9082/PGIS_S_Map/XMLPort";
        
        
var url = "Client";   
        
var param = xmldata+"&"+ urldata;
           
        XMLHttpReq.open(
"post",url,true);   
        XMLHttpReq.setRequestHeader(
"Content-Type","application/x-www-form-urlencoded");   
        XMLHttpReq.onreadyStatechange
= XMLHttpReq.onreadystatechange = processResponse;  
        XMLHttpReq.send(param);
    }   
    
//处理服务器端返回的信息函数   
    function processResponse() {   
        
if (XMLHttpReq.readyState == 4) { // 判断对象状态   
            if (XMLHttpReq.status == 200) { // 信息已经成功返回,开始处理信息   
                Display();   
           } 
else { //页面不正常   
                window.alert("您所请求的页面有异常。");   
            }   
        }   
    }   
    
//网页局部刷新,显示服务器端返回的数据
    function Display() {   
           
var msg=XMLHttpReq.responseText;   
           document.getElementById(
'txtOutput').value=msg;    
    }   
</SCRIPT>
</head>

<body>
<TEXTAREA ID=txtInput rows=15 style="width: 100%"></TEXTAREA>
<input type="button" value="显示结果!" onClick="sendRequest();"> 
<TEXTAREA ID=txtOutput rows=15 style="width: 100%"></TEXTAREA>
</body>
</html>

 

2)服务器端ClientServlet,解析服务器传送过来的xml数据和服务地址,并将xml数据转发到该服务地址

package Sql;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public class ClientServlet extends HttpServlet {

    public void init(ServletConfig config) throws ServletException {
        super.init();
    }

    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
            
    }
    
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
    {
        try 
        {
        //获取需要提交的xml数据和转发的url地址
        String urldata = new String(request.getParameter("url").getBytes("iso-8859-1"), "utf-8");
        String xmldata = new String(request.getParameter("xml").getBytes("iso-8859-1"), "utf-8");

        //设置url连接
        URL url = new URL(urldata);     
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
        conn.setRequestMethod("POST"); // 提交模式   
        
//conn.setConnectTimeout(10000);//连接超时 单位毫秒  
        conn.setReadTimeout(9000);//读取超时 单位毫秒 这一部分可以相对设大一点 避免时间过短 数据传送不回来 出现java.net.SocketTimeoutException: Read timed out错误 
        conn.setDoOutput(true);// 是否输入参数  
        
        
//提交xml数据到该url
        StringBuffer params = new StringBuffer();     
        // 表单参数与get形式一样       
        params.append("xml").append("=").append(xmldata);       
        byte[] bypes = params.toString().getBytes();      
        conn.getOutputStream().write(bypes);// 输入参数     
        
        
//获取从该url反馈回来的数据,并将该数据返回到ajax客户端
        BufferedInputStream in = new BufferedInputStream(conn.getInputStream());    
        byte[] bs = new byte[1024];
        int startpos = 0;
        int num = 0;
        num = in.read(bs, startpos, 1024);
        OutputStream out = response.getOutputStream();
        while (num != -1) {
            out.write(bs, 0, num);
            num = in.read(bs, 0, 1024);
        }
        
        //释放内存
        out.flush();
        out.close();
        in.close();
        conn.disconnect();
        } 
        catch (Exception e) 
        {
            e.printStackTrace();
        } 
        
    }
}

 

3)服务器web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
    xmlns
="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation
="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
>
   
    
  <servlet>
    <servlet-name>ClientServlet</servlet-name>
    <servlet-class>Sql.ClientServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ClientServlet</servlet-name>
    <url-pattern>/Client</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

 

 

 

     此外,AJAX跨域还有其他几种方式,具体可以参见

      http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html

      http://zhaohe162.blog.163.com/blog/static/3821679720113219250547/

      http://www.blogjava.net/itspy/archive/2007/02/11/99262.html