频道栏目
首页 > 资讯 > JavaScript > 正文

AJAX跨域总结

17-01-16        来源:[db:作者]  
收藏   我要投稿

我们这个项目前端使用antD,antD是采用React封装的一套组件库,目前开源http://ant.design/,所有组件都是拿来即用,大大缩短了开发周期,强烈推荐。React是单页面应用,通过ajax与后台通信,而antD调试部署在8000端口,后台又是运行在另一个端口,前后台通信跨域。AJAX跨域一般有两种解决方法:CORS(跨域资源共享)和JSONP。

先来看看JSONP,本质原理利用script标签src属性可以跨域的特性,我们自己也可以去实现JSONP,动态添加删除script标签:

function loadJs() {
  var script = document.createElement("script");
  script.src = "http://xxxxxx/get/req";
  document.body.appendChild(script);

  script.onload = function() {
    callback(); 
    document.body.removeChild(script);
  }
} 

在AJAX中使用JSOP:

$.ajax({
   url: 'http://xxxxxx/get/req', 
   cache: false,
   type: 'post',
   jsonp:'callback',
   dataType:'jsonp', 
   success: function (result) {
      //处理结果的过程
   },
   error: function (XMLHttpRequest) {
      //出错回调处理
   }
});

相应的后台代码:

/**
 * 测试
 * 
 * @throws IOException
 */
@RequestMapping("/get/req")
@ResponseBody
public void getData(HttpServletRequest req, HttpServletResponse rep) throws IOException {
    Map<string, object=""> result = null;
    result = manager.getDatas();
    String callback = req.getParameter("callback");
    String json = JSONObject.toJSONString(result);
    rep.setContentType("text/javascript");
    rep.setCharacterEncoding("utf-8");
    PrintWriter out = rep.getWriter();
    out.print(callback + "(" + json + ")");
}

CORS分为简单请求和非简单请求,非简单请求的请求方法不是POST、GET、HEAD,或者header中包含一些特殊请求头,以及Content-Type不是application/x-www-form-urlencoded、multipart/form-data、text/plain的请求。向后台发送请求时会多发送一次option请求,并且不能携带cookie,这个后面再说。CORS只需服务器端在每次响应中设置一些响应头即可,将这些操作放在Filter中实现低耦合:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletResponse rep = (HttpServletResponse) response;
    HttpServletRequest req = (HttpServletRequest) request;
    rep.addHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
    rep.setHeader("Access-Control-Allow-Credentials", "true");//跨域携带cookie
    rep.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");//非简单请求
    rep.setContentType("application/json; charset=utf-8");
    rep.setHeader("Access-Control-Allow-Methods","GET,POST,PUT,DELETE");//非简单请求
    chain.doFilter(request, rep);
}

我们的项目需要接入统一登录中心,SSO大家也知道,每次请求来了之后SSOClient判断是否携带token,过期或者没有token会重定向到登录页面让用户进行登录。这里出现了一个问题,前端向后台发送AJAX请求,在用户没有登录时并不能正常重定向到登录中心,而是出现前台到登录中心页面的XMLHttpRequest跨域错误提示。但是通过浏览器直接输入后台请求URL地址,在用户没有登录时,会重定向到登录中心页面。对于这个问题的产生一开始没有头绪,进行了多种尝试之后定位到了原因。

这里涉及到浏览器是如何处理AJAX请求重定向,当服务器将302响应发给浏览器,浏览器并不是直接进行AJAX回调处理,而是先执行302重定向,从Response Headers中读取Location信息,然后向Location中的Url发出请求,在收到这个请求的响应后才会进行AJAX回调处理。antD是个单页面应用,前后台交互通过AJAX的方式,所以当SSOFilter拦截ajax请求之后,浏览器会首先重定向到登陆中心,产生了前台到登录中心的跨域AJAX请求,当浏览器发现响应头信息没有包含Access-Control-Allow-Origin字段,从而抛出XMLHttpRequest cannot load的错误。

CORS请求默认不发送Cookie和http认证信息,如果要把Cookie发送到服务器,一方面需要服务器同意,指定Access-Control-Allow-Credentials响应头,另一方面必须在AJAX中打开withCredentials属性,$.ajaxSetup方法设置AJAX请求的默认参数选项,多个AJAX请求时,不用为每一个请求配置请求的参数:

$.ajaxSetup({
   xhrFields: {
     withCredentials: true
   },
 })
相关TAG标签
上一篇:js页面跳转并传值的常用方法
下一篇:css3弹性伸缩布局
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站