为什么浏览器在经过身份验证的XMLHttpRequest之后不重用授权头?

 晓亮居士_264 发布于 2023-02-10 09:42

我正在使用Angular开发单页应用程序.后端公开需要基本身份验证的REST服务.获取index.html或任何脚本不需要身份验证.

我有一个奇怪的情况:我的观点的人有一个,其中src是一个REST API需要验证的URL.它由浏览器处理,我没有机会为它所做的GET请求设置授权标头.这会导致浏览器提示输入凭据.

我尝试通过这样做解决这个问题:

    img src在源空

    在"文档就绪"中,使用Authorization标头创建XMLHttpRequest一个service(/api/login),以便进行身份验证.

    完成该调用后,设置该img src属性,认为到那时,浏览器会知道在后续请求中包含Authorization标头...

......但事实并非如此.图像请求没有标题.如果我输入凭据,则页面上的所有其他图像都是正确的.(我也试过和Angular的ng-src但是产生了相同的结果)

我有两个问题:

    为什么浏览器(IE10)在成功后的所有请求中都没有包含标题XMLHttpRequest

    我该怎么做才能解决这个问题?


@bergi询问了请求的详细信息.他们来了.

请求/ api /登录

GET https://myserver/dev30281_WebServices/api/login HTTP/1.1
Accept: */*
Authorization: Basic 
Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729) Connection: Keep-Alive

响应(/ api/login)

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 4
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 20 Dec 2013 14:44:52 GMT

要求/ user/picture/2218:

GET https://myserver/dev30281_WebServices/api/user/picture/2218 HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET CLR 3.0.30729)
Connection: Keep-Alive

然后Web浏览器会提示输入凭据.如果我输入它们,我得到这个回复:

HTTP/1.1 200 OK
Cache-Control: public, max-age=60
Content-Length: 3119
Content-Type: image/png
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 20 Dec 2013 14:50:17 GMT

ComFreek.. 24

基本的想法

通过JavaScript加载图像并将其显示在网站上.优点是身份验证凭据永远不会进入HTML.他们会在JavaScript方面抗拒.

第1步:通过JS加载图像数据

这是基本的AJAX功能(另请参阅XMLHttpRequest::open(method, uri, async, user, pw)):

var xhr = new XMLHttpRequest();
xhr.open("GET", "your-server-path-to-image", true, "username", "password");

xhr.onload = function(evt) {
  if (this.status == 200) {
    // ...
  }
};

第2步:格式化数据

现在,我们如何显示图像数据?使用HTML时,通常会src为图像元素的属性分配URI .我们可以在这里应用相同的原则,除了我们使用数据URI而不是"普通" http(s)://派生的事实.

xhr.onload = function(evt) {
  if (this.status == 200) {
    var b64 = utf8_to_b64(this.responseText);
    var dataUri = 'data:image/png;base64,' + b64; // Assuming a PNG image

    myImgElement.src = dataUri;
  }
};

// From MDN:
// https://developer.mozilla.org/en-US/docs/Web/API/window.btoa
function utf8_to_b64( str ) {
    return window.btoa(unescape(encodeURIComponent( str )));
}

帆布

还有另一个选项,包括在字段中绘制加载的数据.这样,用户将无法右键单击图像(画布所在的区域),而不是用户在查看图像属性面板时将看到长数据URI的数据URI.

2 个回答
  • 基本的想法

    通过JavaScript加载图像并将其显示在网站上.优点是身份验证凭据永远不会进入HTML.他们会在JavaScript方面抗拒.

    第1步:通过JS加载图像数据

    这是基本的AJAX功能(另请参阅XMLHttpRequest::open(method, uri, async, user, pw)):

    var xhr = new XMLHttpRequest();
    xhr.open("GET", "your-server-path-to-image", true, "username", "password");
    
    xhr.onload = function(evt) {
      if (this.status == 200) {
        // ...
      }
    };
    

    第2步:格式化数据

    现在,我们如何显示图像数据?使用HTML时,通常会src为图像元素的属性分配URI .我们可以在这里应用相同的原则,除了我们使用数据URI而不是"普通" http(s)://派生的事实.

    xhr.onload = function(evt) {
      if (this.status == 200) {
        var b64 = utf8_to_b64(this.responseText);
        var dataUri = 'data:image/png;base64,' + b64; // Assuming a PNG image
    
        myImgElement.src = dataUri;
      }
    };
    
    // From MDN:
    // https://developer.mozilla.org/en-US/docs/Web/API/window.btoa
    function utf8_to_b64( str ) {
        return window.btoa(unescape(encodeURIComponent( str )));
    }
    

    帆布

    还有另一个选项,包括在<canvas>字段中绘制加载的数据.这样,用户将无法右键单击图像(画布所在的区域),而不是<img>用户在查看图像属性面板时将看到长数据URI的数据URI.

    2023-02-10 09:45 回答
  • 谷歌驱动器上传器使用角度js创建.它的作者遇到了类似的问题.这些图标托管在不同的域上,并将它们视为img src=违反了CSP.因此,和你一样,他们不得不使用XHR获取图标图像,然后以某种方式设法将它们放入img标签中.

    他们描述了他们如何解决它.在使用XHR获取图像后,他们将其写入HTML5本地文件系统.他们把它的URL中的本地文件系统中imgsrc使用属性ng-src指令.

    $http.get(doc.icon, {responseType: 'blob'}).success(function(blob) {
      console.log('Fetched icon via XHR');
      blob.name = doc.iconFilename; // Add icon filename to blob.
      writeFile(blob); // Write is async, but that's ok.
      doc.icon = window.URL.createObjectURL(blob);
      ...
    }
    

    至于为什么,我不知道.我假设创建用于检索图像的会话令牌是不可能的?我希望Cookie标头会被发送?这是跨来源请求吗?在这种情况下,您是否设置了withCredentials属性?这可能是P3P的事吗?

    2023-02-10 09:46 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有