spring-boot + jsonp решает внешние междоменные проблемы

задняя часть внешний интерфейс сервер браузер
spring-boot + jsonp решает внешние междоменные проблемы

Теперь давайте обсудим вопросы, связанные с данными запроса браузера из разных источников. Это может быть не очень стандартно, потому что отказ от данных междоменного запроса не уникален для браузеров Причина, по которой междоменные запросы не могут быть сделаны, заключается в том, что браузеры в основном реализуют спецификацию безопасности, называемую «Политика единого происхождения». Что именно представляет собой эта спецификация? Мы нашли профиль на MDN по следующему адресу:

Объяснение политики одинакового происхождения браузера

Как правило, когда URL-адрес A и URL-адрес B находятся в协议,端口,域名При наличии различий браузер активирует политику одного и того же источника и отклоняет запросы данных между серверами А и Б.

Если говорить о стратегии единоначалия, то на бумаге она поверхностна, и я абсолютно точно знаю, что это дело надо реализовать. Ниже я продемонстрирую шаг за шагом с кодом.

1. Ситуация, когда сервер А не может запросить сервер Б

Поскольку это междоменный домен, я предполагаю, что у меня есть два доменных имени, а именноAа такжеlocalhost,AУказывает, что Xiaobian размещает доменное имя в облаке Alibaba.localhostКак следует из названия, это моя машина для разработки. Мы представляем сценарий, в которомlocalhostразвернутьindex.htmlфайл, вAРазверните простойspring-bootФоновый сервис и предоставить простой интерфейс, доступный дляindex.htmlВызов файла и, наконец, запрос браузераlocalhostизindex.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файл, который выглядит так:

Можно обнаружить, что запрос был отклонен браузером, подсказав нам, что данные междоменного запроса не разрешены, что очень неудобно, как это решить?

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файл, результат такой:

Вышеупомянутый путь через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 — лишь одно из них, и конкретную ситуацию необходимо детально проанализировать. Я надеюсь, что эта статья будет вам полезна, спасибо за прочтение, добро пожаловать на githubstart, мва!