我正在使用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: BasicAccept-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方面抗拒.
这是基本的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) { // ... } };
现在,我们如何显示图像数据?使用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.
通过JavaScript加载图像并将其显示在网站上.优点是身份验证凭据永远不会进入HTML.他们会在JavaScript方面抗拒.
这是基本的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) { // ... } };
现在,我们如何显示图像数据?使用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.
谷歌驱动器上传器使用角度js创建.它的作者遇到了类似的问题.这些图标托管在不同的域上,并将它们视为img src=
违反了CSP.因此,和你一样,他们不得不使用XHR获取图标图像,然后以某种方式设法将它们放入img
标签中.
他们描述了他们如何解决它.在使用XHR获取图像后,他们将其写入HTML5本地文件系统.他们把它的URL中的本地文件系统中img
的src
使用属性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的事吗?