配置xhr.withCredentials = true对请求的影响以及预检请求

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

一、withCredentials 是什么?

withCredentials = true 是 XMLHttpRequest 对象的一个属性设置。当将其设置为 true 时,意味着在跨域请求中,浏览器会在请求中包含凭据(如 cookies、HTTP 认证或客户端 SSL 证书),即使是跨域请求也会发送这些凭据。

1、当客户端配置xhr.withCredentials = true,表示允许在进行跨域请求时携带凭证信息,如Cookie,Session
等信息,否则是携带不过去的。

2、当客户端配置此属性时,会产生跨域问题 , 因为当客户端配置了withCredentials , 服务端如果配置了允许跨域
例如Access-Control-Allow-Origin:* 。 那么此时就会报错跨域,原因是当携带cookie等凭证时候,就是指定了服
务器必须给Access-Control-Allow-Origin明确的IP来源 , 不能是通配符 * , 会被视为此次的HTTP不安全。解决
方案一般会动态配置请求头res.setHeader('Access-Control-Allow-Origin', req.headers.origin); 动态设置
允许的客户端的IP3、一般来讲,客户端配了withCredentials = true,允许携带凭证,服务端也是需要同步配置此属性为True才可
以收到凭证的。但当客户端是简单请求(不会发起Options预检请求)的时候,服务端是可以收到cookie凭证的,所
以最好是按规矩来,服务端和客户端都要配置。

二、讨论下刚刚讲到的Options预检请求

   2.1 预检请求是什么 ?
       预检请求(Preflight Requests)是跨域请求中的一种机制,通过发送一个 OPTIONS 请求来确认实际请求是否
安全,并检查服务器是否支持特定的跨域请求。这个预检请求包含一系列头部信息,例如 Origin,用于指示实际请求的
来源。服务器根据这些信息来决定是否允许实际请求的发送。

   2.2 为什么要发起预检请求? 
       上面说到预检请求是跨域请求中的一种机制,确认实际请求是否安全。
       它存在的原因是因为客户端禁止非同源请求, 当发生跨域请求时,请求实际会被服务器正常处理,只是在响应的时
候被客户端给拦截掉并且抛出了一个跨域的错误。 
       仔细想下如果没有预检请求投石问路,那么一旦真的实际请求产生了跨域被客户端拦截。此时发生的情况是:请
求已经被服务器正常处理,并且修改了数据库的数据,客户端跨域报错,客户看不到数据的变化,但是实际数据已经发生了
变化, 就会出现数据被误修改的问题。 所以预检请求投的石问路存在是必要的,确保跨域请求可以被正常处理,不会出
现数据错乱问题。

   2.3 预检请求什么时候会被发送?CORS机制中,客户端将请求分为两种:
     1、简单请求(需同时满足以下条件):
          ● 请求方法是以下三种之一:GET,HEAD,POSTHTTP的头信息不超出以下几种字段:
             Accept,Accept-Language,
             Content-Language,
             Last-Event-ID,
             Content-Type
           ● Content-Type的值仅限以下三种:
             text\plain,
             multipart/form-data,
             application/x-www-form-urlencoded
     
     2、非简单请求(但凡不同时满足上面两个条件,就属于非简单请求)会触发预检请求。

模拟发送预检请求 , 添加自定义请求的头部字段,将请求标记为复杂请求。

   xhr.setRequestHeader("token", "thisisatoken");
   此时服务端即使配置了跨域也会报错跨域问题,原因是因为服务端也需要配置字段token,相当一个招呼吧,允
   许添加定义字段token,相当于白名单。

res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, token');

三、心得感悟

一切的焦虑都来源于不甘现状又无能为力,唯有自身强大,才能无所畏惧。
行路难,多不易,不知未来,即走好当下每一步,走好了今天,才可能会有更好的明天 !

还是刚刚的问题 报错和url实际路径没关系 function sendAutoMKCOL() { const resultDiv = document.getElementById(‘mkcolResult’); resultDiv.textContent = “正在发送MKCOL请求…”; resultDiv.style.backgroundColor = “#e0e0e0”; // 修正1:使用具体资源路径 const url = serverUrl; // 修正2:先发送OPTIONS预检请求 const preflight = new XMLHttpRequest(); preflight.open("OPTIONS", url, true); preflight.setRequestHeader("Origin", window.location.origin); preflight.setRequestHeader("Access-Control-Request-Method", "MKCOL"); preflight.setRequestHeader("Access-Control-Request-Headers", "Depth"); // 关键修复3:添加超时处理 preflight.timeout = 5000; // 5秒超时 preflight.ontimeout = function() { resultDiv.textContent = "OPTIONS请求超时"; resultDiv.style.backgroundColor = "#ffcdd2"; }; preflight.onload = function() { console.log("OPTIONS响应状态:", preflight.status); console.log("响应头:", preflight.getAllResponseHeaders()); // 打印所有响应头 if (preflight.status === 200) { // 修正3:预检成功后发送MKCOL请求 //显示完整响应信息(包括头部和正文 // 关键修复4:验证CORS头 const allowOrigin = preflight.getResponseHeader("Access-Control-Allow-Origin"); const allowMethods = preflight.getResponseHeader("Access-Control-Allow-Methods"); if (allowOrigin !== "http://192.168.0.1:80") { resultDiv.textContent = `CORS Origin不匹配: ${allowOrigin}`; resultDiv.style.backgroundColor = "#ffcdd2"; return; } if (!allowMethods.includes("MKCOL")) { resultDiv.textContent = `MKCOL方法未允许: ${allowMethods}`; resultDiv.style.backgroundColor = "#ffcdd2"; return; } const mkcol = new XMLHttpRequest(); mkcol.open("MKCOL", url, true); // 修正4:添加必须的Depth头 /* mkcol.setRequestHeader(“Depth”, “1”); mkcol.setRequestHeader(“Content-Type”, “application/xml”); */ mkcol.onload = function() { if (mkcol.status >= 200 && mkcol.status < 300) { resultDiv.textContent = `MKCOL成功! 状态码: ${mkcol.status}`; resultDiv.style.backgroundColor = "#e8f5e9"; } else { resultDiv.textContent = `MKCOL失败: ${mkcol.status} ${mkcol.statusText}`; resultDiv.style.backgroundColor = "#ffebee"; } }; mkcol.onerror = function() { resultDiv.textContent = "MKCOL请求失败,请检查CORS配置"; resultDiv.style.backgroundColor = "#ffcdd2"; }; mkcol.send(); } else { resultDiv.textContent = `预检失败: ${preflight.status} ${preflight.statusText}`; resultDiv.style.backgroundColor = "#ffcdd2"; } }; preflight.onerror = function() { resultDiv.textContent = "OPTIONS预检请求失败"; resultDiv.style.backgroundColor = "#ffcdd2"; }; preflight.send(); }
最新发布
10-22
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值