spring-boot + jsonp 解决前端跨域问题

栏目: Json · 发布时间: 6年前

内容简介:现在咱们一起来讨论浏览器跨域请求数据的相关问题。说这样可能不是很标准,因为拒绝跨域请求数据并不是浏览器所独有的,之所以会出现跨域请求不了数据,是因为浏览器基本都实现了一个叫"同源策略"的安全规范。该规范具体是什么呢?我们在MDN上找到了一份资料,地址如下:总的来说,当A网址和B网址在

现在咱们一起来讨论浏览器跨域请求数据的相关问题。说这样可能不是很标准,因为拒绝跨域请求数据并不是浏览器所独有的,之所以会出现跨域请求不了数据,是因为浏览器基本都实现了一个叫"同源策略"的安全规范。该规范具体是什么呢?我们在MDN上找到了一份资料,地址如下:

浏览器同源策略讲解

总的来说,当A网址和B网址在 协议端口域名 方面存在不同时,浏览器就会启动同源策略,拒绝A、B服务器之间进行数据请求。

说了同源策略,纸上得来终觉浅,绝知此事要躬行,到底同源策略是怎么体现的呢?下面我将结合代码一步一步进行演示。

1、A服务器请求不了B服务器的情况

既然是跨域,我就假设我有两个域名,分别是 Alocalhost , A 表示小编在阿里云上主机域名, localhost 顾名思义就是小编的开发机器了。我们想象这样一个场景,在 localhost 上部署一个 index.html 文件,在 A 服务器上部署一个简单的 spring-boot 后台服务,并提供一个简单的接口暴露给 index.html 文件调用,最后浏览器请求 localhostindex.html 文件,看浏览器提示什么?

index.html

<!DOCTYPE html>
<html>
<head>
<title>测试跨域访问</title>
<meta charset="utf-8"/>
</head>
<body>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            $.ajax({
                type : "get",
                async : true,
                url : "http://A/hello/map/getUser.json",// 请求A服务器上的接口
                type : "json",
                success : function(data) {
                // 打印返回的数据
                console.log("success,and return data is " + data);
                }
            });
        });
    </script>
        <h2>hello world</h2>
</body>
</html>

浏览器上请求 index.html 文件,显示如下:

spring-boot + jsonp 解决前端跨域问题

可以发现,请求被浏览器给拒绝了,提示我们不允许跨域请求数据,很难受,怎么解决呢?

2、使用 jsonp 解决跨域请求

首先讲下原理,jsonp解决跨域问题主要利用了 <script> 标签的可跨域性,也就是 src 属性中的链接地址可以跨域访问的特性,因为我们经常将 src 属性值设置为cdn的地址,已加载相关的js库。

index.html

<!DOCTYPE html>
<html>
<head>
<title>测试跨域访问</title>
<meta charset="utf-8" />
</head>
<body>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript">
    	$(document).ready(function() {
        	$.ajax({
        		type : "get",
        		async : true,
        		jsonp : "callbackName",// 后端接口参数名
        		jsonpCallback : "callbackFunction", // 回调函数名
        		url : "http://A/hello/map/getUser.json",
        		dataType : "jsonp", // 数据格式为 jsonp
        		success : function(data) {
        			console.log("success");
        		}
        	});
    	});
    </script>
    <script type="text/javascript">
    	var callbackFunction = function(data) {
    		alert('接口返回的数据是:' + JSON.stringify(data));
    	};
    </script>
</body>
</html>

A 服务器上的接口代码为:

/**
 * 
 * The class JsonBackController.
 *
 * Description:该控制器返回一串简单的json数据,json数据由一个简单的User对象组成
 *
 * @author: huangjiawei
 * @since: 2018年6月12日
 * @version: $Revision$ $Date$ $LastChangedBy$
 *
 */
@RestController
@RequestMapping(value = "/map")
public class JsonBackController {
    private static final Logger logger = LoggerFactory.getLogger(JsonBackController.class);
    /**
     * 解决跨域请求数据
     * @param response
     * @param callbackName 前端回调函数名
     * @return
     */
    @RequestMapping(value = "getUser.json")
    public void getUser(HttpServletResponse response, @RequestParam String callbackName) {
        User user = new User("huangjiawei", 22);
        response.setContentType("text/javascript");
        Writer writer = null;
        try {
        	writer = response.getWriter();
        	writer.write(callbackName + "(");
        	writer.write(user.toString());
        	writer.write(");");
        } catch (IOException e) {
        	logger.error("jsonp响应写入失败! 数据:" + user.toString(), e);
        } finally {
        	if (writer != null) {
        		try {
        			writer.close();
        		} catch (IOException e) {
        			logger.error("输出流关闭异常!", e);
        		}
        		writer = null;
        	}
        }
    }
}

后端传入一个参数 callbackName 回调函数名,然后返回一段js代码给前端,js代码格式如下:

callbackName + ( data ) + ;

浏览器请求 localhost 服务器上的 index.html 文件,结果如下:

spring-boot + jsonp 解决前端跨域问题

上面这种方式是通过 jquery + jsonp 解决跨域问题的,刚刚不是说可以用 <script> 标签的 src 属性吗?四的。

localhost 服务器上的 index.html

<!DOCTYPE html>
<html>
<head>
<title>测试跨域访问</title>
<meta charset="utf-8" />
</head>
<body>
	<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
	<script type="text/javascript">
		var callbackFunction = function(data) {
			alert('接口返回的数据是:' + JSON.stringify(data));
		};
	</script>
	<script type="text/javascript" src="http://A/hello/map/getUser.json?callbackName=callbackFunction"></script>
</body>
</html>

浏览器显示效果和上面一致。但此处需要注意的是, src 表示引入一个js文件,由于是直接调用接口,而接口返回的数据又刚好是一段js代码,故能被执行。另外,第二个 <script> 标签顺序不能颠倒,不然会出现 callbackFunction 函数找不到的情况。

工程代码地址 : github.com/SmallerCode…

最后总结下,解决跨域的方案有很多种,jsonp只是其中一种,具体情况需要具体分析。希望此文对你有帮助,谢谢阅读,欢迎github给颗 start ,么么哒!


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Zero to One

Zero to One

Peter Thiel、Blake Masters / Crown Business / 2014-9-16 / USD 27.00

“This book delivers completely new and refreshing ideas on how to create value in the world.” - Mark Zuckerberg, CEO of Facebook “Peter Thiel has built multiple breakthrough companies, and ......一起来看看 《Zero to One》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具