CORS目录
- 一、SpringBoot 跨域设置
- 二、CORS
- (1)总结的图如下
- (2)简单请求满足的条件
- (3)响应头
- (4)请求头
- (5)使用XMLHttpRequest进行跨域访问
- 1. Access-Control-Allow-Methods
- 2. Access-Control-Allow-Headers
- 3. 总结
- 三、跨域的情况
- 四、参考
一、SpringBoot 跨域设置
方便拿来用的同学使用,详细的请往下看。
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration htmlGet = new CorsConfiguration();
htmlGet.addAllowedOrigin("*");
htmlGet.setAllowCredentials(true);
htmlGet.addAllowedMethod("*");
htmlGet.addAllowedHeader("*");
htmlGet.addExposedHeader("*");
UrlBasedCorsConfigurationSource corsConfigurationSource
= new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**", htmlGet);
return new CorsFilter(corsConfigurationSource);
}
}
二、CORS
跨域访问资源其实就是浏览器通过自身的权限,控制HTTP请求访问服务器资源,服务器和浏览器是基于HTTP请求头进行交流,例如:服务器通过Access-Control-Allow-Origin、Access-Control-Allow-Methods等类似的请求头告诉浏览器,我这个资源只能特定的源、某一组method才能进行访问。总结来说:服务器基于HTTP头声明哪些源通过浏览器的权限能访问服务器的哪些资源。
(1)总结的图如下
CORS权限验证的流程有两种,分别是简单请求和预检。
- 简单请求可以直接发起请求。
- 不是简单请求则需要预检,预检没问题之后才会发起真正的请求。
(2)简单请求满足的条件
- 使用下列方法之一:
GET
HEAD
POST
- 除了被用户代理自动设置的标头字段(例如
Connection
、User-Agent
或其他在 Fetch 规范中定义为禁用标头名称的标头),允许人为设置的字段为 Fetch 规范定义的对 CORS 安全的标头字段集合。该集合为:Accept
Accept-Language
Content-Language
Content-Type
(需要注意额外的限制)Range
(只允许简单的范围标头值 如bytes=256-
或bytes=127-255
)
Content-Type
标头所指定的媒体类型的值仅限于下列三者之一:text/plain
multipart/form-data
application/x-www-form-urlencoded
- 如果请求是使用
XMLHttpRequest
对象发出的,在返回的XMLHttpRequest.upload
对象属性上没有注册任何事件监听器;也就是说,给定一个XMLHttpRequest
实例xhr
,没有调用xhr.upload.addEventListener()
,以监听该上传请求。 - 请求中没有使用
ReadableStream
对象。
(3)响应头
- Access-Control-Allow-Origin
告诉浏览器允许访问的源。
- Access-Control-Expose-Headers
XMLHttpRequest.getResponseHeader可以访问的请求头,如果不设置只能访问Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。
- Access-Control-Max-Age
- Access-Control-Allow-Credentials
- Access-Control-Allow-Methods
- Access-Control-Allow-Headers
(4)请求头
这些请求头都是浏览器自己设置的,不能通过正常的API更改。
- Origin
- Access-Control-Request-Method
- Access-Control-Request-Header
(5)使用XMLHttpRequest进行跨域访问
API
@RequestMapping("/cors")
@RestController
public class CorsController {
@GetMapping(value = "/html")
public String html(HttpServletResponse response) {
return "<div>GET</div>";
}
@DeleteMapping(value = "/delete")
public String delete(HttpServletResponse response) {
return "<div>DELETE</div>";
}
}
1. Access-Control-Allow-Methods
function get() {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8080/cors/html')
xhr.onreadystatechange = function() {
console.log('status', xhr.readyState)
}
xhr.send();
}
@Bean
public CorsFilter corsFilter() {
CorsConfiguration htmlGet = new CorsConfiguration();
htmlGet.addAllowedOrigin("null");
htmlGet.addAllowedMethod("DELETE");
UrlBasedCorsConfigurationSource corsConfigurationSource
= new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/cors/html", htmlGet);
return new CorsFilter(corsConfigurationSource);
}
可以看到CORS异常了,XMLHTTPRequest请求是GET,服务器Access-Control-Allow-Methods是DELETE,换成人话说:服务器只允许DELETE请求。
把htmlGet.addAllowedMethod("DELETE");
改成htmlGet.addAllowedMethod("GET");
2. Access-Control-Allow-Headers
function get() {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8080/cors/html')
xhr.onreadystatechange = function() {
console.log('status', xhr.readyState)
}
xhr.setRequestHeader('headxxx', 'a');
xhr.send();
}
@Bean
public CorsFilter corsFilter() {
CorsConfiguration htmlGet = new CorsConfiguration();
htmlGet.addAllowedOrigin("null");
htmlGet.addAllowedMethod("DELETE");
htmlGet.addAllowedHeader("Token");
UrlBasedCorsConfigurationSource corsConfigurationSource
= new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/cors/html", htmlGet);
return new CorsFilter(corsConfigurationSource);
}
因为我们的请求头headxxx不在简单请求的范围内(上面写了),所以浏览器发起了预检。服务器只接收Token请求头,所以浏览器通过对比后发现http请求不满足服务器的规则。不是简单请求都会触发预检。
把xhr.setRequestHeader('headxxx', 'a');
改成xhr.setRequestHeader('Token', 'a');
3. 总结
后面的就不去验证了,到这里我们已经知道CORS其实就是浏览器设置的一道权限,服务器可以通过Access-Control-Allow-Methods、Access-Control-Allow-Headers、Access-Control-Allow-Origin等特定的请求头去限制源的访问。