如何在跨域请求中允许带入原网站的cookie(401:not authorizated)

本文详细探讨了在项目开发过程中遇到的跨域请求问题,特别是关于如何让浏览器自动携带已存在的认证信息Cookie进行跨域请求的方法。文章通过具体示例介绍了如何正确设置withCredentials属性以实现这一目的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

博主在项目开发中,遇到一个问题,在当前网页,发送一个跨域请求,可是浏览器给我报401:not authorizated。一开始以为是我写的http请求没有带入一些身份验证信息,后来仔细研究了下,此跨域请求没有带包含认证信息的cookie,可是我看了项目中别的http请求压根没有单独去设置这种cookie。
我又看了下Chrome—》 DevTools—》application—》Cookies,发现包含认证信息的cookie已经全部在当前域下了。说明我在发送请求时,并不需要自己在重新设置cookie值了;既然已经有cookie值,为什么我发送的请求的Request Headers里没有自动带上已经存在的cookie呢?
所以我在怀疑是不是因为我发送的请求时跨域的呢?
带着这个怀疑,我着重看了下CORS跨域相关文档。

一. CORS

Cross-Origin Resource Sharing 是 W3C 推出的一种跨站资源获取的机制。

首先我们来看一下浏览器的支持情况:


ChromeFirefox (Gecko)Internet ExplorerOperaSafari
43.58 & 9(XDomainRequest), 10124

移动端的浏览器对这种方法的支持比较完善。
现在我们看到了,如果不需要兼容 IE6、7的话,就可以使用这种方法。

这种跨域方案主要的思想是:服务器 在响应头中设置相应的选项,浏览器如果支持这种方法的话就会将这种跨站资源请求视为合法,进而获取资源。

1.服务端可以设置的响应头信息:
  • (1) Access-Control-Allow-Origin
    Access-Control-Allow-Origin: <origin> | *

    origin: 被允许跨域访问这个资源的网站,* 代表全部网站。浏览器会检测这个参数,如果符合要求,才会去获取资源。
    举个例子,允许 http://jasonkid.github.io/fezone 来跨域访问这个资源:
    Access-Control-Allow-Origin: http://jasonkid.github.io/fezone

  • (2) Access-Control-Allow-Credentials
    Access-Control-Allow-Credentials: true | false
    表示是否允许浏览器携带 Cookie 来访问这个资源。
    这个属性要和 XMLHttpRequest 的 withCredentials 属性来配合使用。

    var xhr = new XMLHttpRequest();
    var url = 'http://foo.other/resources/credentialed-content/';
    
    if(xhr) {
        xhr.open('GET', url, true);
        xhr.withCredentials = true; // 设置带有 Cookie 的资源请求
        xhr.onreadystatechange = handler;
        xhr.send(); 
    }
    
  • (1) XMLHttpRequest 对象中指定了 withCredentials = true

  • (2) 服务器响应头中 Access-Control-Allow-Credentials: true

  • (3) 服务器响应头中 Access-Control-Allow-Origin 不能为 *

以下选项主要是安全性配置的问题,主要是服务器的配置问题了,就不展开介绍了:

Access-Control-Expose-Headers

Access-Control-Allow-Methods

Access-Control-Allow-Headers

所以,在发送跨域请求时之所以没能带上cookie,很有可能是因为ajax没有设置`withCredentials = true`这一属性。
那么继续研究下withCredentials属性是干啥吃的。。

二.withCredentials

查阅MSDN《火狐开发者文档》,发现有详细介绍:

XMLHttpRequest.withCredentials  属性是一个Boolean类型,它指示了是否该使用类似cookies,authorization headers(头部授权)或者TLS客户端证书这一类资格证书来创建一个跨站点访问控制(cross-site Access-Control)请求。在同一个站点下使用withCredentials属性是无效的。

此外,这个指示也会被用做响应中cookies 被忽视的标示。默认值是false。

如果在发送来自其他域的XMLHttpRequest请求之前,未设置withCredentials 为true,那么就不能为它自己的域设置cookie值。而通过设置withCredentials 为true获得的第三方cookies,将会依旧享受同源策略,因此不能被通过document.cookie或者从头部相应请求的脚本等访问。

注: 永远不会影响到同源请求

Note: 不同域下的XmlHttpRequest 相应,不论其Access-Control- header 设置什么值,都无法为它自身站点设置cookie值,除非它在请求之前将withCredentials 设为true。

实例
<code>
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://example.com/', true);
    xhr.withCredentials = true;
    xhr.send(null);
</code>

详见:
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/withCredentials

到此,已经很明白了,解决上述的问题就是需要设置xhr.withCredentials = true这一项。
但是,我是使用JQuery封装的ajax,所以需要借助$.ajax()方法的
xhrFields属性。(xhrFields是一个具有多个”字段名称-字段值”对的对象,用于对本地XHR对象进行设置。)

    jQuery.ajax({
        url: "https:" + _ENV_ + "api/1.0.0-beta/urlManager/getParameter",
        type:"get",
        contentType:"application/json",
        data:{
            "md5":gs_all_params.gs_md5,
            "rt":new Date().getTime()
        },
        xhrFields: {
            withCredentials: true
        },
        success:function(response){
            window[APP_ENV].gs_params =Object.assign(response.Parameter,gs_all_params) ;
            createApp();
        },
        error:function() {
        }
});

运行后,不再报错并且得到了正确的结果。

总结:
出现这个问题,是因为本人对跨域请求带上原网站的cookie的相关知识不太了解,通过这次报错正好学习到了,因此记录下来供大家借鉴。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值