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: GET, POST
//允许所有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 方法
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)
原文始发于微信公众号(前端24):CORS介绍及HTTP跨域请求解决方法
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/217147.html