CORS介绍及HTTP跨域请求解决方法

CORS介绍及HTTP跨域请求解决方法

CORS 跨域资源共享

CORS(Cross-Origin Resource Sharing 跨域资源共享)是一个W3C标准,是一种网络浏览器的技术规范。它使用额外的 HTTP 头来告诉浏览器,让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。
CORS 机制允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。现代浏览器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch )使用 CORS,以降低跨域 HTTP 请求所带来的风险

需要使用CORS的情况:

  • 由 XMLHttpRequest 或 Fetch 发起的跨域 HTTP 请求
  • Web 字体 (CSS 中通过 @font-face 使用跨域字体资源), 因此,网站就可以发布 TrueType 字体资源,并只允许已授权网站进行跨站调用
  • WebGL 贴图
  • 使用 drawImage 将 Images/video 画面绘制到 canvas

HTTP跨域请求的解决方法

后端设置响应头:

配置允许跨域访问的源:
//允许指定源访问
Access-Control-Allow-Origin: https://blog.csdn.net/weixin_45426836
//允许所有源访问
Access-Control-Allow-Origin: *
配置允许跨域访问的HTTP请求方法:
//允许指定HTTP请求方法访问
Access-Control-Allow-Methods: GETPOST
//允许所有HTTP请求方法访问
Access-Control-Allow-Methods: *
配置允许跨域访问的请求头:
Access-Control-Allow-Headers: <header-name>[, <header-name>]*
配置允许跨域访问携带Cookie:
Access-Control-Allow-Credentials: true
//此时允许跨域访问的源不能为*,需要指定具体的源
Access-Control-Allow-Origin: https://blog.csdn.net/weixin_45426836

//前端请求需要做相关配置:withCredentials: true
//例如:原生js
var xhr = new XMLHttpRequest()
xhr.open("get","https://me.csdn.net/weixin_45426836",true)
xhr.withCredentials = true;   
xhr.send()
xhr.onload = function(){
    
    
     console.log(xhr.response)  
}
//例如:JQuery
$.ajax({
    
      
  url : 'https://me.csdn.net/weixin_45426836',  
  method: 'get'
  xhrFields: {
    
      
    withCredentials: true  
  },  
  success : function(data) {
    
      
    console.log(data);  
  }  
});  
//例如:axios
axios('https://me.csdn.net/weixin_45426836', {
    
      
  method: 'get',  
  withCredentials: true,  
}).then(data => {
    
      
	console.log(data);
}).catch(err => {
    
    
	console.log(err);
});

CORS预检请求(preflight request):

在 Web 服务器处理跨域访问时,对那些 HTTP 非简单请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器会先使用 OPTIONS 方法发起一个预检请求(preflight request),来获取服务端是否允许此次跨域请求。服务器确认允许后,才会发起实际的 HTTP 请求,在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)

HTTP简单请求:不触发CORS预检请求

若满足以下所有条件,则该请求可视为简单请求

  • HTTP请求方法为:GET, HEAD, POST
  • Fetch 规范定义的对 CORS 安全的首部字段集合,不得人为设置该集合之外的其他首部字段:Accept, Accept-Language, Content-Language, Content-Type (需要注意额外的限制), DPR, Downlink, Save-Data, Viewport-Width, Width
  • Content-Type 的值仅限于:text/plain, multipart/form-data, application/x-www-form-urlencoded
  • 请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器,XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问
  • 请求中没有使用 ReadableStream 对象
HTTP非简单请求:触发CORS预检请求

若满足以下任一条件,则该请求可视为非简单请求

  • HTTP请求方法为:PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH
  • 设置了对 CORS 安全的首部字段集合之外的其他首部字段:Accept, Accept-Language, Content-Language, Content-Type (需要注意额外的限制), DPR, Downlink, Save-Data, Viewport-Width, Width
  • Content-Type 的值不属于:application/x-www-form-urlencoded, multipart/form-data, text/plain
    -请求中的XMLHttpRequestUpload 对象注册了任意多个事件监听器
  • 请求中使用了ReadableStream对象

HTTP 请求首部字段:

以下为可用于发起跨域请求的首部字段。这些首部字段无须手动设置, 当使用 XMLHttpRequest 对象发起跨域请求时,它们就被设置好了

Origin

指定预检请求或实际请求的源站URI

Access-Control-Request-Method

将实际请求所使用的 HTTP 方法告诉服务器,用于预检请求

Access-Control-Request-Headers

将实际请求所携带的首部字段告诉服务器,用于预检请求

HTTP 响应首部字段:

以下为规范所定义的响应首部字段

Access-Control-Allow-Origin

指定允许访问该资源的外域 URI的具体值,* 表示允许来自所有域的请求

Access-Control-Allow-Methods

指定实际请求所允许使用的 HTTP 方法。逗号分隔的一个具体的字符串,* 表示允许使用所有 HTTP 方法

扫描二维码关注公众号,回复: 11906021 查看本文章
Access-Control-Allow-Headers

指定实际请求中允许携带的请求头首部字段

Access-Control-Allow-Credentials

指定是否允许发送Cookie。默认为false:不允许发送Cookie,true:允许发送Cookie。对服务器有特殊要求的非简单HTTP请求(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求)这个值只能设为true

Access-Control-Expose-Headers

指定实际请求中允许携带的首部字段。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定

Access-Control-Max-Age

指定本次预检请求的有效期,单位为秒。在有效内,请求的结果能够被缓存,不用发出另一条预检请求

参考资料

MDN文档:HTTP访问控制(CORS)

猜你喜欢

转载自blog.csdn.net/weixin_45426836/article/details/103957991