这段时间面试 经常会问到这个问题. 也就是说, 如果你的前端想要获取其他域名下的数据, 前端需要如何请求, 后端需要如何设置.
最常见的处理方式有两种
方法一, 在 java 代码中设置 response.setHeader("Access-Control-Allow-Origin","*"); 即可解决 ajax 跨域的问题, 其中星号代表允许全部请求
- $.ajax({
- type: "post",
- url: "http://192.168.1.88/testAjaxJson",
- contentType: "application/json",
- dataType: "json",
- success: function(){
- alert("request succeed");
- }
- });
- @Controller
- public class TestController {
- /**
- * 使用普通 json 方式跨域请求
- * @param response
- */
- @RequestMapping(value="/testAjaxJson")
- public void testAjaxJson(HttpServletResponse response){
- try {
- // 这里设置为任意域请求都能获取到数据
- response.setHeader("Access-Control-Allow-Origin","*");
- // 这里还可以设置接收方式, 固定域 二者选其一
- response.setHeader("Access-Control-Allow-Headers", "accept, content-type");
- response.setHeader("Access-Control-Allow-Method", "POST");
- response.setHeader("Access-Control-Allow-Origin", "http://192.168.1.88");
- response.getWriter().print("{\"id\":1}");
- response.flushBuffer();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
在正式 post 之前, 浏览器会先发出一个 options 请求(也叫 preflight), 同时 header 带上 origin 还有 Access-Control-Request-*:** 之类的头, 服务器响应会返回相应的 access-control-allow-origin, 如果匹配, 那么浏览器就会发送正式 post, 否则就会出现上述错误. 这也解答了, 跨域访问时, 我们明明发送的 post 请求, 失败的话, 查看 chrome network 会发现是 options 方法的原因.
这里的 content-type 不属于 (application/x-www-form-urlencoded,multipart/form-data,text/plain) 中的任何一种, 所以是复杂请求.
复杂请求 第一次是 options 请求, http options 请求跟 get,post,head 等一样, 都属于 http 的请求方法, options 方法, 用来获取服务器端某 url 支持的方法, response header 中 allow 标志支持的方法
第二次才是真正的请求
方法二, 使用 jsonp 的方式请求数据, 后端需返回 js 方法调用, 返回的数据放在参数中
- function testJsonp(){
- $.ajax({
- url:"http://192.168.1.88/testAjaxJsonp",
- type:"GET",// 必须是 get 请求
- dataType:"jsonp",// 请求的数据类型
- jsonp:"callback",// 请求类型是回调
- jsonpCallback:"callbackFunction",// 数据请求成功时回调的方法
- data:{
- },// 请求的数据
- success:function(data){// 执行完成返回的数据
- alert(data.id);// 输出值是 1
- }
- });
- }
- @Controller
- public class TestController {
- @RequestMapping(value="/testAjaxJsonp")
- public void testAjaxJsonp(@RequestParam String callback,HttpServletResponse response){
- try {
- // 这里 jsonp 返回的数据是固定格式 文后有详细解释
- response.getWriter().print(callback+"({\"id\":1})");
- response.flushBuffer();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
jsonp 跨域的原理解析
jsonp 的最基本的原理是: 动态添加一个 < script > 标签, 而 script 标签的 src 属性是没有跨域的限制的. 这样说来, 这种跨域方式其实与 ajax XmlHttpRequest 协议无关了.
JSONP 是一个非官方的协议, 它允许在服务器端集成 Script tags 返回至客户端, 通过 javascript callback 的形式实现跨域访问 JSONP 即 JSON with Padding. 由于同源策略的限制, XmlHttpRequest 只允许请求当前源 (域名, 协议, 端口) 的资源. 如果要进行跨域请求, 我们可以通过使用 html 的 script 标记来进行跨域请求, 并在响应中返回要执行的 script 代码, 其中可以直接使用 JSON 传递 javascript 对象. 这种跨域的通讯方式称为 JSONP.
jsonCallback 函数 jsonp123(....): 是浏览器客户端注册的, 获取跨域服务器上的 json 数据后, 回调的函数
Jsonp 原理:
首先在客户端注册一个 callback (如:'jsoncallback'), 然后把 callback 的名字 (如: jsonp123) 传给服务器. 注意: 服务端得到 callback 的数值后, 要用 jsonp123(......)把将要输出的 json 内容包括起来, 此时, 服务器生成 json 数据才能被客户端正确接收.
然后以 javascript 语法的方式, 生成一个 function , function 名字就是传递上来的参数'jsoncallback'的值 jsonp123
最后将 json 数据直接以入参的方式, 放置到 function 中, 这样就生成了一段 js 语法的文档, 返回给客户端.
客户端浏览器, 解析 script 标签, 并执行返回的 javascript 文档, 此时 javascript 文档数据, 作为参数,
传入到了客户端预先定义好的 callback 函数 (如上例中 jquery $.ajax() 方法封装的的 success: function (json))里.(动态执行回调函数)
可以说 jsonp 的方式原理上和 < script src="http:// 跨域 /...xx.js"></script > 是一致的 (qq 空间就是大量采用这种方式来实现跨域数据交换的) .JSONP 是一种脚本注入(Script Injection) 行为, 所以也有一定的安全隐患.
注意, jquey 是不支持 post 方式跨域的.
希望总结可以帮助到大家
来源: https://www.cnblogs.com/adidas1/p/9473036.html