关于CORS的笔记

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权限验证的流程有两种,分别是简单请求和预检。

  1. 简单请求可以直接发起请求。
  2. 不是简单请求则需要预检,预检没问题之后才会发起真正的请求。

关于CORS的笔记_第1张图片

(2)简单请求满足的条件

  • 使用下列方法之一:
    • GET
    • HEAD
    • POST
  • 除了被用户代理自动设置的标头字段(例如 ConnectionUser-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 "
GET
"
; } @DeleteMapping(value = "/delete") public String delete(HttpServletResponse response) { return "
DELETE
"
; } }

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等特定的请求头去限制源的访问。

三、跨域的情况

  • XMLHttpRequest 或 Fetch API 发起的跨源 HTTP 请求。
  • Web 字体(CSS 中通过 @font-face 使用跨源字体资源),因此,网站就可以发布 TrueType 字体资源,并只允许已授权网站进行跨站调用。
  • WebGL 贴图。
  • 使用 drawImage() 将图片或视频画面绘制到 canvas。
  • 来自图像的 CSS 图形 (en-US)
  • 四、参考

    跨域资源共享(CORS)

你可能感兴趣的:(笔记)