?
相信刚开始接触从xml配置文件转到java类实现配置功能的过程中,些许都会有些疑惑,配置文件到底该怎么写,我要实现多少接口,new多少对象,完全不知道怎么入手。
今天,在学习了跨域的相关配置后,学到了一点点自定义配置的思路。在此做下记录,也为学习讨论。本文主体分为两部分,第一部分介绍跨域问题,第二部分介绍如何编写配置类
?
?
跨域的本质是浏览器针对ajax请求,规定当前页面下发送的ajax请求的域名应该和当前页面的域名一致,达到阻止跨站攻击的目的。通常该跨域问题只针对ajax,而不会针对静态文件(图片等)
而以下四种情况会导致跨域问题:
条件 | 示例 |
---|---|
域名不同 | www.a.com与www.b.com |
域名相同端口不同 | www.a.com:80与www.a.com:81 |
二级域名不同 | x.a.com与y.a.com |
协议不同 | http与https |
?
解决跨域的方法有以下三种
Jsonp
实现方法:通过<script>
标签的src发送请求路径获取伪装成js脚本的json数据
缺点:只能发送GET请求,添加额外标签繁琐
?
CORS全称Cross-origin resource sharing(跨域资源共享)为W3C的一个标准,它允许浏览器向跨源服务器,发出XMLHttpRequest(ajax底层对象)请求,从而克服了AJAX只能同源使用的限制。
?
浏览器处理ajax请求分为简单请求和特殊请求
简单请求
只要同时满足以下两大条件,就属于简单请求。:
(1) 请求方法是以下三种方法之一:
(2)HTTP的头信息不超出以下几种字段:
application/x-www-form-urlencoded
、multipart/form-data
、text/plain
简单请求重点:
当浏览器发现发起的ajax请求是简单请求时,会在请求头中携带一个字段:Origin
简单请求过程解析:
浏览器会在请求头信息携带Origin字段(例:Origin:http://a.baidu.com{协议+域名+端口}),服务器根据该Origin值决定是否允许跨域
响应信息:
Access-Control-Allow-Origin: http://a.baidu.com
Access-Control-Allow-Credentials: true
Content-Type: text/html; charset=utf-8
注意事项:
如果要使用cookie除了设置Access-Control-Allow-Credentials: true
外,Access-Control-Allow-Origin: http://a.baidu.com
必须为具体的域名!!!
?
特殊请求
除了简单请求之外,都为特殊请求
特殊请求重点:
特殊请求会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。该预检请求会在请求头携带一个OPTIONS
字段
特殊请求过程解析(有关判断使用三元运算符?:)
发送预检请求==》服务器检查该域名是否在许可名单中?答复浏览,浏览器发送正式XMLHttpRequest
请求:报错
预检请求模板:
OPTIONS /cors HTTP/1.1
Origin: http://a.baidu.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.leyou.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
与简单请求相比,除了Origin以外,多了两个头:
答复浏览器模板:
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://a.baidu.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Max-Age: 1728000
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
除了Access-Control-Allow-Origin
和Access-Control-Allow-Credentials
以外,这里又额外多出3个头:
?
终于到了激动人心的撸码环节了,以下开始介绍如何编写配置类,以解决跨域问题
@Configuration注解
作用于类上,声明当前类为配置类,相当于xml文件
@Bean
作用于方法上,将当前方法的返回值对象注入spring容器上下文(contex)中
因为本次为了解决跨域问题,所以需要使用CorsFilter对象。因此直接return new CorsFilter();
点进CorsFilter发现该构造方法需要一个CorsConfigurationSource对象作为参数
public CorsFilter(CorsConfigurationSource configSource) {
Assert.notNull(configSource, "CorsConfigurationSource must not be null");
this.configSource = configSource;
}
所以需要new出一个CorsConfigurationSource的对象,但是点进CorsConfigurationSource发现该类为一个接口,因此应该找一个实现类进行实例化
点击该CorsConfigurationSource接口发现有一个实现类(UrlBasedCorsConfigurationSource)实现了该接口
public class UrlBasedCorsConfigurationSource implements CorsConfigurationSource
接着通过new该实现类(UrlBasedCorsConfigurationSource),通过阅读源码的注释了解到,该类下的registerCorsConfiguration可以注册CORS配置信息
/**
* Register a {@link CorsConfiguration} for the specified path pattern.
*/
public void registerCorsConfiguration(String path, CorsConfiguration config) {
this.corsConfigurations.put(path, config);
}
根据该信息发现该方法需要两个参数,一个是需要拦截的路径,一个是配置类对象
如法炮制,通过查看CorsConfiguration源码,发现该类可以直接new,并且有无参构造方法,所以,直接new对象,并对该对象属性赋初始值,完成该配置类的构造。
最后,将所有初始化后的对象赋值到方法的参数列表中
原文:https://www.cnblogs.com/guaosky/p/12405755.html