AJAX跨域完全讲解

今天在慕课网上学习了AJAX跨域完全讲解:https://www.imooc.com/learn/947

我在收集AJAX面试题的时候其实就已经有过AJAX跨域的问题的了,当时候知道了为什么会存在跨域,以及跨域解决的方案有哪些,今天随着课程的学习,又加深了AJAX跨域的理解,以此记录下来。

为什么会发生产生跨域问题?

上面的图也很清晰了,因为浏览器为了安全(同源),本身就限制了。

  • 当我们发送XMLHttpRequest请求的时候,如果请求的是别的域(主机域名、端口)不同时,那么就会产生跨域问题(客户端无法获取服务端返回的数据)

值得注意的是:跨域的问题是发生在XMLHttpRequest请求的,也就是说,不是XMLHttpRequest请求是不会有跨域问题的

  • 举个很简单的例子:在编写网页的时候,<img = src = www.xxxx.xxxx/ >,URL不是本域的还是可以正常获取该图片的

解决跨域问题的思路

明显地,跨域的问题是由于浏览器限制的,是XMLHttpRequest才会发生的,那么我们可以以这个思路去找找解决思路:

对于浏览器的问题,可以使用相关的参数进行启动浏览器,是可以解决跨域的问题,但是通用性是极低的,了解即可。

JSONP解决跨域

JSONP是JSON使用的一种补充方式,不是官方的协议。JSONP是一种解决跨域问题的一种协议

JSONP这种解决方案其实现在已经很少用了(复杂一点,需要修改后台代码),但我们可以适当了解一下。

使用步骤

在后端增加一个控制器,继承AbstractJsonpResponseBodyAdvice类,完整代码如下:


@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice { public JsonpAdvice() {
// TODO Auto-generated constructor stub
super("callback2");
}
}

前端ajax请求:



// 服务器返回的结果
var result; $.ajax({
url: base +"/get1",
dataType: "jsonp",
jsonp: "callback2", //是否需要缓存,如果这里没有配置缓存,那么请求的URL还会有一个参数
cache:true,
success: function(json){
result = json;
}
});

注意的是,前端AJAX的jsonp: "callback2",要和我们的Controllersuper("callback2");是一致的,不然是不会有效的。

JSONP原理是动态创建script来进行请求的:

JSONP的弊端:

  • 要对服务器的代码进行改动
  • 只支持GET方法(原理是动态创建script来进行请求的)
  • 发送的不是XMLHttpRequest请求(XMLHttpRequest请求有很多好用的特性)

参考资料:

CORS解决跨域问题

CORS解决跨域问题(也就是我们服务端被调用方解决跨域的思路)

对于CORS是怎么理解的,我就直接摘抄一下:https://segmentfault.com/a/1190000012469713#articleHeader8的了。

在Java中,我们写下面这个过滤器,就可以完全解决跨域的问题了:



package com.imooc;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.tomcat.util.buf.StringUtils; public class CrosFilter implements Filter { @Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub } @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub HttpServletResponse res = (HttpServletResponse) response; HttpServletRequest req = (HttpServletRequest) request; //带cookie的时候,origin必须是全匹配,不能使用*
String origin = req.getHeader("Origin");
if (!org.springframework.util.StringUtils.isEmpty(origin)) {
res.addHeader("Access-Control-Allow-Origin", origin);
}
res.addHeader("Access-Control-Allow-Methods", "*"); // 支持所有自定义头和预检命令(非简单请求会有预检命令)
String headers = req.getHeader("Access-Control-Request-Headers");
if (!org.springframework.util.StringUtils.isEmpty(headers)) {
res.addHeader("Access-Control-Allow-Headers", headers);
} res.addHeader("Access-Control-Max-Age", "3600");
// enable cookie
res.addHeader("Access-Control-Allow-Credentials", "true");
chain.doFilter(request, response);
} @Override
public void destroy() {
// TODO Auto-generated method stub } }

上面提到了非简单请求,那什么是非简单请求呢,可以看下面的图:

非简单请求会发出一个预检命令的(当然了,我们上面的Filter已经解决预检命令的问题了):

Spring框架解决

如果使用的是Spring框架的话,那就只需要一个注解就能够解决跨域的问题了@CrossOrigin

HTTP服务器层

我们在的商用开发中,一般请求的过程是这样的:浏览器->HTTP服务器(Nginx,Apache)->应用服务器(Tomcat,Weblogic)

上面编写的Filter、Spring框架都是在应用服务器上解决的,我们也是可以通过HTTP服务器(Nginx,Apache)来进行解决跨域问题的

Nginx我用过,Apache我倒是还没用过,下面就简单记录了Nginx和Apache是如何配置的:

Nginx配置:

Apache配置:

代理解决跨域问题

在之前的图我们已经看到了,解决跨域的问题可以在“调用方”中来进行解决。

“调用方”解决跨域的问题是这个思路的:让发送出去的请求代理成是本域的

举个例子:

www.zhongfucheng.top是调用方

www.zhongfucheng.site是被调用方

它俩是不同域的,但我们可以在nginx或Apache上进行配置代理:将被调用方www.zhongfucheng.site映射成别的路径

比如,像下面的图,将8080端口的映射成了ajaxServer,当调用方访问ajaxServer路径时,这样的方法在外部看起来就不像是跨域了,像是访问本地(8081端口),但实际访问别的域(8080端口)

总结

令我感到最简单的是通过Spring的注解就可以解决跨域的问题了,JSONP的方式已经是很少用的了,因为存在一定的弊端,但了解一下也无妨,毕竟可能面试的时候会问到。当没有用任何框架的时候,写Filter也不麻烦,也只是配置了一下HTTP头信息而已。如果使用Nginx、Apache时,也可以用代理或者配置HTTP头信息都可以解决。看完之后,有没有觉得跨域问题就迎刃而解了。


如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章的同学,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y

AJAX跨域完全讲解的更多相关文章

  1. ajax跨域原理以及解决方案

    说明 跨域主要是由于浏览器的“同源策略”引起,分为多种类型,本文主要探讨Ajax请求跨域问题 前言 强烈推荐阅读参考来源中的文章,能够快速帮助了解跨域的原理 参考来源 本文参考了以下来源 浏览器同源政 ...

  2. AJAX跨域调用相关知识-CORS和JSONP(引)

    AJAX跨域调用相关知识-CORS和JSONP 1.什么是跨域 跨域问题产生的原因,是由于浏览器的安全机制,JS只能访问与所在页面同一个域(相同协议.域名.端口)的内容. 但是我们项目开发过程中,经常 ...

  3. ajax跨域相关

    ajax 技术使用xmlhttprequest组件附送请求时,发送请求的url和本网页的url地址必须在同一个域名下如果需要跨域,可以使用iframe或者<javascript src=&quo ...

  4. ajax跨域请求学习笔记

    原文:ajax跨域请求学习笔记 前言 ajax,用苍白的话赞扬:很好. 我们可以使用ajax实现异步获取数据,减少服务器运算时间,大大地改善用户体验:我们可以使用ajax实现小系统组合大系统:我们还可 ...

  5. Javascript&Ajax-深入浅出JSONP--解决ajax跨域问题

    Javascript&Ajax-深入浅出JSONP--解决ajax跨域问题 原理讲解: 链接地址:http://www.cnblogs.com/chopper/archive/2012/03/ ...

  6. Ajax 跨域难题 - 原生 JS 和 jQuery 的实现对比

    讲解顺序: AJAX 的概念及由来 JS 和 jQuery 中的 ajax 浏览器机制 AJAX 跨域 AJAX 的概念 在讲解 AJAX 的概念之前,我先提一个问题. 这是一个典型的 B/S 模式. ...

  7. Ajax跨域问题及解决方案 asp.net core 系列之允许跨越访问(Enable Cross-Origin Requests:CORS) c#中的Cache缓存技术 C#中的Cookie C#串口扫描枪的简单实现 c#Socket服务器与客户端的开发(2)

    Ajax跨域问题及解决方案   目录 复现Ajax跨域问题 Ajax跨域介绍 Ajax跨域解决方案 一. 在服务端添加响应头Access-Control-Allow-Origin 二. 使用JSONP ...

  8. e3mall商城总结11之sso系统的分析、应用以及解决ajax跨域问题

    说在前面的话 一.sso系统分析 什么是sso系统 SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次 ...

  9. Laravel中的ajax跨域请求

    最近接触Laravel框架ajax跨域请求的过程中遇到一些问题,在这里做下总结. 一开始发起ajax请求一直报500错误,搜索相关资料后发现Laravel要允许跨域请求可以加入Cors中间件,代码如下 ...

随机推荐

  1. ThinkPhp关闭Debug后出错解决方案

    注:我使用的是ThinkPHP的3.2版本,其他版本类似 从自己入手PHP开发以来,一直使用的是ThinkPHP的框架,前几天偶然间碰到了一个错误,在Debug模式下网站一切正常,而关闭Debug进行 ...

  2. python3 第二十二章 - 函数式编程之Decorator(装饰器)

    前面我们说了,在python中,一切皆对象.函数也是一个对象,而且函数对象可以被赋值给变量,通过变量也能调用该函数.如: def sayHello(name): print(name + ' hell ...

  3. Django_xadmin_应用外键搜索功能错误

    问题: 当我在给某一张表加上外键搜索的时候,会出现 TypeError: Related Field got invalid lookup: icontains 问题原因: a 表关联 b表,也就是说 ...

  4. CSS深入理解学习笔记之line-height

    1.line-height的定义 定义:两行文字基线之间的距离. 注:不同字体之间的基线是不同的. 2.line-height与行内框盒子模型 行内框盒子模型: ①内容区域(content area) ...

  5. 译-BSA NSH Command介绍

    BSA NSH Command全称BMC BladeLogic Network Shell Command,是基于ZSH的shell. 1 说明 NSH命令行(全称Network  Shell,又称为 ...

  6. discuz数据库相关表

    discuz 数据表对照cdb_access               用户权限表      cdb_adminactions         管理动作表cdb_admingroups        ...

  7. LVS-DR模式(原理图详解)

    标签(空格分隔): linux 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 前言 LVS一共四种工作模式.其中,DR模式是比较常用的模式之一,配置较麻烦,这里 ...

  8. 【JDK1.8】JDK1.8集合源码阅读——Set汇总

    一.前言 这一篇里,我将对HashSet.LinkedHashSet.TreeSet进行汇总分析,并不打算一一进行详细介绍,因为JDK对Set的实现进行了取巧.我们都知道Set不允许出现相同的对象,而 ...

  9. PowerMockito使用详解

    一.PowerMock概述 现如今比较流行的Mock工具如jMock,EasyMock,Mockito等都有一个共同的缺点:不能mock静态.final.私有方法等.而PowerMock能够完美的弥补 ...

  10. Django的admin.py注册流程

    通常创建一个Django项目的时候,在Django的配置文件settings.py中,都会有下面的这段配置: INSTALLED_APPS = [ 'django.contrib.admin', 'd ...