天天看点

跨域实现-jsonp/CORS,什么是跨域,怎么解决以及相关代码都有详细介绍,确定要错过吗?

在说明跨域问题之前呢咱们首先来说一下伪静态

1.什么是伪静态:

伪静态是相对真实静态来讲的,通常我们为了增强搜索引擎的友好面,都将文章内容生成静态页面,但是有的朋友为了实时的显示一些信息。或者还想运用动态脚本解决一些问题。不能用静态的方式来展示网站内容。但是这就损失了对搜索引擎的友好面。怎么样在两者之间找个中间方法呢,这就产生了伪静态技术。伪静态技术是指展示出来的是以html一类的静态页面形式,但其实是用ASP一类的动态脚本来处理的。

总结: 以.html为结尾的展现的动态页面的脚本技术.

2. 搜索引擎工作原理(铺垫)

跨域实现-jsonp/CORS,什么是跨域,怎么解决以及相关代码都有详细介绍,确定要错过吗?

大前端技术发展比较火. 完全的前后端分离 node.js 作为脚手架 存.html的页面 .jsp技术可能落后了. 通过vue/jquery 动态实现页面数据回显. VUE

3.什么是跨域

要想弄明白什么是跨域就要知道什么是同源策略,要想知道什么是同源策略就要先知道什么是源。

源:如果两个页面(接口)的协议,端口或者域名都相同,那么两个页面就有相同的源。

下表给出了相对http://store.company.com/dir/page.html同源检测的示例:

URL 结果 原因

http://store.company.com/dir2/other.html 成功

http://store.company.com/dir/inner/another.html 成功

https://store.company.com/secure.html 失败 不同协议 ( https和http )

http://store.company.com:81/dir/etc.html 失败 不同端口 ( 81和80)

http://news.company.com/dir/other.html 失败 不同域名 ( news和store )

同源策略

同源策略是浏览器的一个安全限制,从一个源加载的文档或者脚本默认不能访问另一个源的资源。例如a.com/111/html页面不能访问b.com/person这种接口,因为他们是不用的源。

注意:下面几个不受同源策略限制

1、页面中链接(例如页面的<a href="http://www.w3school.com.cn" target="_blank" rel="external nofollow" >W3School</a>)、重定向和表单提交不受同源策略限制

2、跨域资源的引入是不受同源策略的限制,但是js读不到其中的内容。<script src="..."></script>,<img>,<link>,<iframe>等。

怎么解决跨域

介绍生产中最常用的两种解决跨域的方法。CORS解决跨域问题和通过代理解决跨域问题。

CORS解决跨域问题

CORS是Cross-Origin Resources Sharing的简写,中文翻译为“跨域资源共享”,是W3C的标准。通过CORS,浏览器允许向其他源服务器发送资源请求。

设置CORS需要浏览器和服务器两个方面支持。目前基本上主流的浏览器都支持CORS(IE 8 和 9 需要通过 XDomainRequest 来实现),所以只要后端服务支持CORS,就能够实现跨域。服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符(*)则表示所有网站都可以访问资源。要实现CORS跨域其实非常简单,说白了就是在服务端设置一系列的HTTP头,主要分为请求头和响应头,在请求和响应时加上这些HTTP头即可轻松实现CORS。

虽然设置 CORS 和前端没什么关系,但是通过这种方式解决跨域问题的话,会在发送请求时出现两种情况,分别为简单请求和复杂请求。针对不同的情况,服务端的设置也不一样。

CORS原理说明

用户可以向普通的ajax请求一样发起跨域请求. get/post/put/delete,由于当下的跨域的业务比较常见,所有的主流的浏览器默认支持跨域. CORS核心需要配置服务器端是否允许跨域

服务器实现CORS跨域

说明: 服务器端如果需要实现CORS跨域请求,则需要在服务器端标识允许跨域的网址即可

页面信息:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>
<script type="text/javascript" src="http://manager.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
	/*$(){}结构必然是jQuery函数类库导入后才能正确执行*/
	$(function(){
		alert("我执行了AJAX");
		$.get("http://manager.jt.com/corsjson.json",function(data){
			alert(data.name);
		})
	})
</script>
</head>
<body>
	<h1>JSON跨域请求测试</h1>
</body>
</html>
           

 编辑json数据

跨域实现-jsonp/CORS,什么是跨域,怎么解决以及相关代码都有详细介绍,确定要错过吗?

 编辑CORS跨域

package com.jt.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration  //标识我是一个配置类
public class CorsConfig implements WebMvcConfigurer {

    //扩展跨域请求的方法
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        //1.允许什么样的请求进行跨域
        // /* 只允许一级目录请求    /** 表示多级目录请求.
        registry.addMapping("/**")
        //2.允许哪些服务进行跨域
                .allowedOrigins("*")
                //3.是否允许携带cookie信息
                .allowCredentials(true)
                //4.定义探针检测时间 在规定的时间内不再询问是否允许跨域
                .maxAge(1800);
    }
}

           
  1. 简单请求

    只要同时满足以下两大条件,就属于简单请求

    条件 1:使用下列方法之一:

    GET

    HEAD

    POST

    条件 2:Content-Type 的值仅限于下列三者之一:

    text/plain

    multipart/form-data

    application/x-www-form-urlencoded

  2. 复杂请求

    不符合以上条件的请求就肯定是复杂请求了。

    复杂请求的 CORS 请求,会在正式通信之前,增加一次 HTTP 查询请求,称为"预检"请求,该请求是 option 方法的,通过该请求来向服务端询问从当前源发送请求以及允许的请求方法和请求字段。

通过代理解决跨域问题

实现原理:同源策略是浏览器需要遵循的标准,而如果是请求都发给代理服务器代理服务器再向后端服务器请求就可以规避跨域的问题。

跨域实现-jsonp/CORS,什么是跨域,怎么解决以及相关代码都有详细介绍,确定要错过吗?

在ngnix.conf进行配置就行,不会的话我的Nginx这篇文章中有提到

ajax跨域访问测试(一)

说明:测试时 挑选在jt-manager中的页面和数据进行ajax测试

1.页面结构:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试JSON跨域问题</title>
<script type="text/javascript" src="http://manage.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
	$(function(){
		$.get("http://manage.jt.com/test.json",function(data){
			alert(data.name);
		})
	})
</script>
</head>
<body>
	<h1>JSON跨域请求测试</h1>
</body>
</html>
           

访问的数据类型:

{"id":"1","name":"tom"}
           

测试效果

跨域实现-jsonp/CORS,什么是跨域,怎么解决以及相关代码都有详细介绍,确定要错过吗?

 页面网址: http://manager.jt.com/test.html

页面中ajax请求网址: http://manager.jt.com/test.json

结论: ajax访问同一个域名的数据,访问正常!!!

jsonp实现跨域

跨域的缺点:回调的函数需要提前定义.程序员自己定义.

核心思路:

利用javascript中src属性实现跨域.

客户端定义回调函数 callback=hello

服务端程序封装特定的JSON格式   callback(JSON)  执行回调函数

JSONP介绍

JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析

jQuery实现JSONP

需求:jsonp的方式如果采用原生的调用方式,则配置繁琐 1.javascript 2.自定义回调函数 3.特殊格式封装.

则jQuery负责封装JSONP.像常规ajax调用一样的方便.

页面封装:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSONP测试</title>
<script type="text/javascript" src="http://manager.jt.com/js/jquery-easyui-1.4.1/jquery.min.js"></script>
<script type="text/javascript">
	$(function(){
		alert("测试访问开始!!!!!")
		$.ajax({
			url:"http://manager.jt.com/web/testJSONP",
			type:"get",				//jsonp只能支持get请求   src只能进行get请求.
			dataType:"jsonp",       //dataType表示返回值类型 必须标识
			//jsonp: "callback",    //指定参数名称
			//jsonpCallback: "hello",  //指定回调函数名称
			success:function (data){   //data经过jQuery封装返回就是json串
				alert(data.id);
				alert(data.name);
			}
		});	
	})
</script>
</head>
<body>
	<h1>JSON跨域请求测试</h1>
</body>
</html>
           

controller:

package com.jt.web.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class JSONPController {

    /**
     * 完成JSONP的调用
     * url:http://manager.jt.com/web/testJSONP?callback=jQuery111101021758391465013_1597656788213&_=1597656788214
     * 规定:返回值结果,必须经过特殊的格式封装.callback(json)
     */
    @RequestMapping("/web/testJSONP")
    public String  jsonp(String callback){

        return callback+"({'id':'100','name':'tomcat猫'})";
    }

}

           

最后就可以成功解决啦