跨域实现 -- JSONP & CORS

1. 什么是跨域访问

案例1:
页面网址:http://manage.jt.com:80/test.html
ajax请求: http://manage.jt.com:80/test.json
结论: 当请求协议://域名:port端口号都相同时 访问正常的.

案例2:
页面网址: http://www.jt.com:80/test.html
ajax请求: http://manage.jt.com:80/test.json
结论: 当浏览器的地址与ajax地址不同时,请求不能正常执行.

定义: 当浏览器解析ajax时,ajax发起请求的地址如果与当前页面所在的地址违反同源策略时,则称之为跨域(请求);

2. 同源策略

说明:浏览器在发起ajax请求时,必须遵守同源策略的规定,否则数据无法正常解析.
策略说明:发起请求时,必须满足 协议://域名:端口 都相同(和当前页面对比)时,满足同源策略要求,浏览器可以正确的发起请求,并且解析结果.
但是如果上述的三项中有一项不同,则表示跨域访问,浏览器不予解析返回值结果.
在这里插入图片描述

3. 实现跨域访问

3.1 JSONP

JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的

3.1.2 JSONP跨域实现原理

1).利用JavaScript中的src属性实现跨域

<script type="text/javascript" src="http://manage.jt.com/test.json"></script>

2).自定义回调函数 function callback(){}

function hello(data){
			alert(data.name);
		}

3).将返回值结果 进行特殊的格式封装 callback(JSON数据)

hello({"id":"1","name":"Tom"})

3.1.3 jQuery实现JSONP跨域访问

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>JSONP测试</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(){
		alert("测试访问开始!!!!!")
		//页面位置: www.jt.com/JSON.html
		$.ajax({
			url:"http://manage.jt.com/web/testJSONP",
			type:"get",				//jsonp只能支持get请求,不支持post,因为src不支持post提交
			dataType:"jsonp",       //dataType表示返回值类型,如果是跨越访问,则必须添加jsonp
			jsonp: "callback",    //指定参数名称,一般默认约定都叫callback
			jsonpCallback: "getJSONP",  //指定回调函数名称
			success:function (data){   //data经过jQuery封装返回就是json串
				alert(data.id);
				alert(data.password);
				//转化为字符串使用
				//var obj = eval("("+data+")");
				//alert(obj.name);
			}	
		});	
	})
</script>
</head>
<body>
	<h1>JSON跨域请求测试</h1>
</body>
</html>

3.1.4 页面分析

在这里插入图片描述

3.1.5 编辑JSONPController

说明:在jt-manage 中添加JSONPController实现跨域访问

@RestController
public class JSONPController {
	/**
		http://manage.jt.com/web/testJSONP?callback=getJSONP&_=1595324880197
	 * JSONPObject  专门负责封装JOSNP的返回值结果
	 * 注意事项:  返回值结果必须通过特殊格式封装  callback(JSON数据)
	 * @return
	 */
	@RequestMapping("/web/testJSONP")
	public JSONPObject jsonp(String callback) {
		
		//准备返回数据
		User user = new User();
		user.setId(100L).setPassword("我是密码");
		return new JSONPObject(callback, user);
	}

}

3.2 CORS

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,通过添加请求头信息,将源地址进行标识,之后发往后端服务器.
在这里插入图片描述
实现CORS通信的关键点: 跨域请求由浏览器和服务器共同完成,要求双方都必须统一跨域才行,但是默认的条件下服务器端是不允许跨域的,所以必须经过配置才行.

3.2.1 CORS 实现跨域入门

  • 在common项目中添加跨域配置
//类似于web项目中使用的web.xml配置文件
@Configuration
public class CorsConfig implements WebMvcConfigurer {

	/**
	 * 配置后端服务器可以跨域的清单
	 * 参数说明; addMapping : 什么样的请求可以进行跨域  /web/**   /aa/*
	 * 	/*   匹配一级目录
	 *  /**  匹配多级目录
	 */
	@Override
	public void addCorsMappings(CorsRegistry registry) {
		
		registry.addMapping("/**").allowedOrigins("http://www.jt.com")   //配置源
				.allowedMethods("GET","POST","PUT")   //允许的请求方式
				.allowCredentials(true)    //是否允许携带cookie
				.maxAge(1800);      //允许跨域的持续时间
	}
}

在这里插入图片描述

  • 编辑ajax请求页面
<!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">
	/*$(){}结构必然是jQuery函数类库导入后才能正确执行*/
	$(function(){
		alert("我执行了Cors");
		//利用jQuery发起AJAX请求
		$.get("http://manage.jt.com/web/testCors",function(data){
			alert(data.username);
		})
	})
</script>
</head>
<body>
	<h1>JSON跨域请求测试</h1>
</body>
</html>
  • 编辑CorsController
@RestController
public class CorsController {
	
	@RequestMapping("/web/testCors")
	public User testUser() {
		return new User().setId(10L).setUsername("Cors");
	}

}
  • 查看响应信息
    在这里插入图片描述

4.通过CORS完成用户信息校验

4.1 业务需求

在这里插入图片描述

  • 说明: 当用户添加注册信息时,需要向jt-sso 单点登录系统进行数据的校验,如果数据库中存在/不存在都应该返回相关信息,之后页面提示信息给用户.

4.2 页面JS分析

在这里插入图片描述

  • 注意事项:明确url中的哪些部分一定写死在js中,之后根据检索的功能快速定位JS位置
    在这里插入图片描述
  • 说明: 配置ajax事项JSONP的请求
    在这里插入图片描述

4.3 业务接口文档

在这里插入图片描述

4.4 编辑UserController

	/**
	 * 1.url ; http://sso.jt.com/user/check/{param}/{type}
	 * 2. 参数:param 需要校验的数据
	 *        type  校验的类型
	 * 3.返回结果  :    SysResult对象   data:true/false
	 * 4.jsonp跨域访问
	 * 终极目标: 1.快   省   安全
	 * @param param
	 * @param type
	 * @return
	 */
@RequestMapping("/check/{param}/{type}")
public JSONPObject checUser (@PathVariable String param,@PathVariable Integer type,String callbake){
	boolean flag = userService.checkUser(param,type); //要求返回true/false
	SysResult sysResult = SysResult.success(flag);
	return new JSONPObeject(callback,sysResult);
}

4.5 编辑UserService实现类

@Service
public class UserServiceImpl implements UserService {
	
	@Autowired
	private UserMapper userMapper;
	//如果项目中固定写死的key通过static方式维护
	Map<Integer,String> paramMap;
	
	static{
		Map<Integer,String> map = new HashMap<>();
		map.put(1,"username");
		map.put(2,"phone");
		map.put(3,"email");
		paramMap = map;
	}

	// 校验数据库中是否有数据
	//type为类型,可选参数1 username、2 phone、3 email
	@Override
	public boolean checkUser(String param, Integer type) {
		if (param==null || param=="") {
			throw new IllegalArgumentException("参数不能为空!");
		}
		//1.将type类型转化为具体的字段信息
		String column = paramMap.get(type);
		//2.通过获取数据库中的记录总数,判断是否存在数据
		QueryWrapper<User> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq(column,param);
		int count = userMapper.selectCount(queryWrapper);
		return count>0?true:false;
	}

}

4.6 业务呈现效果

在这里插入图片描述

4.7 优化页面结构

  • 添加状态码的判断编辑jdValidate.js
    在这里插入图片描述

4.8 全局异常处理机制优化

//标识改类是全局异常处理机制的配置类
@RestControllerAdvice //advice通知   返回的数据都是json串
@Slf4j	//添加日志
public class SystemExceptionAOP {
	
	/*
	 * 添加通用异常返回的方法.
	 * 底层原理:AOP的异常通知.
	 * 
	 * 常规手段: 返回SysResult.fail()是正常的,
	 * 跨域访问:  JSONP  必须满足JSONP跨域访问要求  callback(SysResult.fail())
	 * 问题: 如何断定用户使用的跨域方式还是普通业务调用??
	 * 分析: jsonp请求  get请求方式携带?callback参数
	 * 判断依据: 用户参数是否携带callback  ,特点参数,一般条件下不会使用
	 * */
	@ExceptionHandler({RuntimeException.class}) //拦截运行时异常
	public Object systemResultException(HttpServletRequest request,Exception exception) {
		String callback = request.getParamter("callbakc");
		if(StringUtils.isEmpty(callback){   ///不是跨域访问
			log.error("{"+exeption.getMessage()+"}",exception);  //输出日志
			return SysResult.fail();
		}
		String method = request.getMethod();
		if(!method.equalsIgnoreCase("GET"){ //不是get请求,说明不是跨域
			log.error("{"+exeption.getMessage()+"}",exception);  //输出日志
			return SysResult.fail();
		}
		//标识进行JSONP的请求,按照JSONP的方式返回数据
		log.error("{"+exeption.getMessage()+"}",exception);  //输出日志
		return new JSONPObject(callback,SysResult.fall());
	}

4.9 页面效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值