跨域解决方案之一---->JQuery.Ajax JSONP解决跨域访问
2015-02-02 13:33
711 查看
出于安全方面的考虑,各大浏览器都使用同源策略,禁止跨域访问。所谓同源策略,简单地说,就是要求动态内容(如JavaScript)只能阅读与之同源的那些HTTP应答和cookies,而不能阅读来自不同源的内容。同源的判断,应该把握住 协议、域名和端口,只有同协议、同域名、同端口才可以算的上是同源,只要这三者中有一个不同,则两个源就属于不同的源,两者之间的访问则属于跨域访问。关于同源与非同源的判断,可以参照下表(from http://blog.sina.com.cn/s/blog_62d3ddc00101al1b.html)
特别注意两点:
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。
同源策略虽然在安全性方面起到了很大的作用,但是在开发的工程中,也不可避免地会需要跨域访问资源。如目前在很多大型Web项目的开发中,为了应对大并发,常常会采取前后端分开部署,这样就涉及到跨域访问的问题。JSONP是目前应用比较广泛的一种跨域解决方案。JSONP的核心思想是利用JS标签的src属性不受跨域限制进行跨域访问的。其主要执行过程可以总结为:首先在客户端注册一个回调函数,然后把回调函数的名字传给服务器;服务器端将要返回给客户端的数据生成为json格式,同时获取到客户端传过来的回调函数的名字,将要传递的json数据以实参的方式,放到回调函数中,然后将组合成的数据返回给客户端,这样返回给客户端的数据格式则形如:回调函数名(data);客户端则会解析返回的数据,执行预先定义好的回调函数。
JQuery.Ajax中使用JSONP很简单,只需要指定datatype为jsonp格式,至于回调函数,可以采用默认形式,JQuery会自动生成随机函数名,并以默认参数名callback=函数名附加在请求的url后,当然,也可以通过jsonp和jsonpcallback自己定义回调函数的参数名和回调函数名称,这两个参数含义如下(w3c):
---------------------------------------------------------
jsonp
类型:String
在一个 jsonp 请求中重写回调函数的名字。这个值用来替代在
"callback=?" 这种 GET 或 POST 请求中 URL 参数里的 "callback" 部分,比如 {jsonp:'onJsonPLoad'} 会导致将 "onJsonPLoad=?" 传给服务器。
jsonpCallback
类型:String
为 jsonp 请求指定一个回调函数名。这个值将用来取代
jQuery 自动生成的随机函数名。这主要用来让 jQuery 生成度独特的函数名,这样管理请求更容易,也能方便地提供回调函数和错误处理。你也可以在想让浏览器缓存 GET 请求的时候,指定这个回调函数名。
---------------------------------------------------------
在后端,只需要通过request.getParameter("callback")获取到回调函数名,并将数据封装成"回调函数名(data)"的形式返回即可,前端在收到返回结果后,若返回的数据格式正确,则调用success方法,对数据做相应处理,否则调用fail方法。
下面是一个简单的示例,后端使用servlet实现,前端页面部署在http://localhost:8086/容器中,后端代码部署在http://localhost:8080/容器中,由于端口号不同,所以前端页面请求后端servlet时为跨域访问。
前端页面代码如下(部署在http://localhost:8086/):
上述页面发出的请求URL最后形如:
http://localhost:8080/testApp/testServlet?callback=jQuery111107367232164833695_1422853667572,回调函数设置采用JQuery的默认设置。
后端代码如下(部署在http://localhost:8080):
web.xml代码:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>testApp</display-name>
<welcome-file-list>
<welcome-file>/testServlet</welcome-file>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>testServlet</servlet-name>
<servlet-class>com.founder.servlet.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>testServlet</servlet-name>
<url-pattern>/testServlet</url-pattern>
</servlet-mapping>
</web-app>
servlet代码:
使用jsonp方式解决跨域问题,编码简单,而且其兼容性很好,在一些古老的浏览器中都可以运行,不需要XMLHttpRequest或者ActiveX的支持,但是它只支持get请求,所以在应用上也有一定的局限性。
特别注意两点:
第一,如果是协议和端口造成的跨域问题“前台”是无能为力的,
第二:在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”指window.location.protocol +window.location.host,也可以理解为“Domains, protocols and ports must match”。
同源策略虽然在安全性方面起到了很大的作用,但是在开发的工程中,也不可避免地会需要跨域访问资源。如目前在很多大型Web项目的开发中,为了应对大并发,常常会采取前后端分开部署,这样就涉及到跨域访问的问题。JSONP是目前应用比较广泛的一种跨域解决方案。JSONP的核心思想是利用JS标签的src属性不受跨域限制进行跨域访问的。其主要执行过程可以总结为:首先在客户端注册一个回调函数,然后把回调函数的名字传给服务器;服务器端将要返回给客户端的数据生成为json格式,同时获取到客户端传过来的回调函数的名字,将要传递的json数据以实参的方式,放到回调函数中,然后将组合成的数据返回给客户端,这样返回给客户端的数据格式则形如:回调函数名(data);客户端则会解析返回的数据,执行预先定义好的回调函数。
JQuery.Ajax中使用JSONP很简单,只需要指定datatype为jsonp格式,至于回调函数,可以采用默认形式,JQuery会自动生成随机函数名,并以默认参数名callback=函数名附加在请求的url后,当然,也可以通过jsonp和jsonpcallback自己定义回调函数的参数名和回调函数名称,这两个参数含义如下(w3c):
---------------------------------------------------------
jsonp
类型:String
在一个 jsonp 请求中重写回调函数的名字。这个值用来替代在
"callback=?" 这种 GET 或 POST 请求中 URL 参数里的 "callback" 部分,比如 {jsonp:'onJsonPLoad'} 会导致将 "onJsonPLoad=?" 传给服务器。
jsonpCallback
类型:String
为 jsonp 请求指定一个回调函数名。这个值将用来取代
jQuery 自动生成的随机函数名。这主要用来让 jQuery 生成度独特的函数名,这样管理请求更容易,也能方便地提供回调函数和错误处理。你也可以在想让浏览器缓存 GET 请求的时候,指定这个回调函数名。
---------------------------------------------------------
在后端,只需要通过request.getParameter("callback")获取到回调函数名,并将数据封装成"回调函数名(data)"的形式返回即可,前端在收到返回结果后,若返回的数据格式正确,则调用success方法,对数据做相应处理,否则调用fail方法。
下面是一个简单的示例,后端使用servlet实现,前端页面部署在http://localhost:8086/容器中,后端代码部署在http://localhost:8080/容器中,由于端口号不同,所以前端页面请求后端servlet时为跨域访问。
前端页面代码如下(部署在http://localhost:8086/):
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script> <script type="text/javascript" src="js/jquery.easyui.min.js"></script> <script type="text/javascript"> $(function(){ $.ajax({ type : "get", url : "http://localhost:8080/testApp/testServlet", dataType : "jsonp", success : function(data) {//客户端jquery预先定义好的callback函数,成功获取跨域服务器上的json数据后,会动态执行这个callback函数 alert(JSON.stringify(data)); }, error : function() {//数据加载失败 alert("fail"); error.apply(this, arguments); } }); }) </script> </head> <body> this is the first page..... </body> </html>
上述页面发出的请求URL最后形如:
http://localhost:8080/testApp/testServlet?callback=jQuery111107367232164833695_1422853667572,回调函数设置采用JQuery的默认设置。
后端代码如下(部署在http://localhost:8080):
web.xml代码:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>testApp</display-name>
<welcome-file-list>
<welcome-file>/testServlet</welcome-file>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>testServlet</servlet-name>
<servlet-class>com.founder.servlet.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>testServlet</servlet-name>
<url-pattern>/testServlet</url-pattern>
</servlet-mapping>
</web-app>
servlet代码:
package com.founder.servlet; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONObject; /** * 测试servlet */ public class TestServlet extends HttpServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Map<String,String> map=new HashMap<String,String>(); map.put("name", "sherry"); JSONObject json=JSONObject.fromObject(map); String callback=req.getParameter("callback");//得到回调函数名 String s=json.toString(); resp.getWriter().write(callback+"("+s+")");//封装成 回调函数名(data)形式 } }
使用jsonp方式解决跨域问题,编码简单,而且其兼容性很好,在一些古老的浏览器中都可以运行,不需要XMLHttpRequest或者ActiveX的支持,但是它只支持get请求,所以在应用上也有一定的局限性。
相关文章推荐
- 跨域解决方案之一---->JQuery.Ajax JSONP解决跨域访问
- 跨域解决方案之一---->JQuery.Ajax JSONP解决跨域访问
- jfinal jquery解决ajax 跨域访问--jsonp
- 利用JSONP解决AJAX跨域问题的原理与jQuery解决方案
- 利用JSONP解决AJAX跨域问题的原理与jQuery解决方案
- JQuery+ajax+jsonp 跨域访问
- C# 和Jsonp的一个小demo 用jQuery与JSONP轻松解决跨域访问的问题
- JSONP解决跨域提交数据(jquery jsonp Ajax)
- jQuery中利用JSONP解决AJAX跨域问题
- JQuery+ajax+jsonp 跨域访问
- JQuery+ajax+jsonp 跨域访问
- 用jQuery与JSONP来解决跨域访问的问题
- jQuery中利用JSONP解决AJAX跨域问题
- 用jQuery与JSONP来解决跨域访问的问题
- 用jQuery与JSONP轻松解决跨域访问的问题
- JQuery+ajax+jsonp 跨域访问
- IT忍者神龟之jQuery中利用JSONP解决AJAX跨域问题
- 用jQuery与JSONP轻松解决跨域访问的问题
- jQuery中利用JSONP解决AJAX跨域问题
- 用jQuery与JSONP轻松解决跨域访问的问题