为什么浏览器在经过身份验证的 XMLHttpRequest 后不重用授权标头? [英] Why doesn't the browser reuse the authorization headers after an authenticated XMLHttpRequest?
问题描述
我正在使用 Angular 开发单页应用程序.后端公开需要基本身份验证的 REST 服务.获取 index.html 或任何脚本不需要身份验证.
I'm developing Single Page App using Angular. The backend exposes REST services that require Basic authentication. Getting index.html or any of the scripts does not require authentication.
我有一个奇怪的情况,我的一个视图有一个 <img>
,其中 src
是需要身份验证的 REST API 的 url. 由浏览器处理,我没有机会为它发出的 GET 请求设置授权标头.这会导致浏览器提示输入凭据.
I have an odd situation where one of my view has a <img>
where the src
is the url of a REST API that requires authentication. The <img>
is processed by the browser and I have no chance to set the authorization header for GET request it makes. That causes the browser to prompt for credentials.
我试图通过这样做来解决这个问题:
I attempted to fix this by doing this:
- 在源代码中将
img
src
留空 - 在文档准备好"时,使用 Authorization 标头向服务 (
/api/login
) 发出XMLHttpRequest
,以便进行身份验证.立> - 完成该调用后,设置
img src
属性,认为届时浏览器将知道在后续请求中包含 Authorization 标头...
- Leave
img
src
empty in the source - At "document ready", make an
XMLHttpRequest
to a service (/api/login
) with the Authorization header, just to cause the authentication to occur. - Upon completing that call, set the
img src
attribute, thinking that by then, the browser would know to include the Authorization header in subsequent requests...
...但事实并非如此.对图像的请求在没有标题的情况下发出.如果我输入凭据,则页面上的所有其他图像都是正确的.(我也试过和 Angular 的 ng-src
但产生了相同的结果)
...but it doesn't. The request for the image goes out without the headers. If I enter the credentials, then all other images on the page are right.
(I've also tried and Angular's ng-src
but that produced the same result)
我有两个问题:
- 为什么在
XMLHttpRequest
成功后,浏览器 (IE10) 没有在所有请求中包含标头? - 我可以做些什么来解决这个问题?
- Why didn't the browser (IE10) include the headers in all requests after a successful
XMLHttpRequest
? - What can I do to work around this problem?
<小时>
@bergi 询问请求的详细信息.在这里.
请求/api/login
Request to /api/login
GET https://myserver/dev30281_WebServices/api/login HTTP/1.1
Accept: */*
Authorization: Basic <header here>
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)
Response (/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:
Request to /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 浏览器会提示输入凭据.如果我输入它们,我会收到以下回复:
And then the web browser prompts for credentials. If I enter them, I get this response:
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
推荐答案
基本思路
通过 JavaScript 加载图像并将其显示在网站上.优点是身份验证凭据永远不会进入 HTML.他们会在 JavaScript 方面抵制.
Basic idea
Load the images via JavaScript and display them on the site. The advantage is that the authentication credentials will never find their way into the HTML. They will resist at the JavaScript side.
这是基本的 AJAX 功能(另见 <代码>XMLHttpRequest::open(method, uri, async, user, pw)):
That's basic AJAX functionality (see also 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.除了我们使用 data URIs 之外,我们可以在这里应用相同的原则'正常' http(s)://
派生.
Step 2: format the data
Now, how can we display the image data? When using HTML, one would normally assign an URI to the src
attribute of the image element. We can apply the same principle here except for the fact that we use data URIs instead of 'normal' http(s)://
derivates.
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.
Canvas
There is also another option which consists in painting the loaded data in a <canvas>
field. This way, the user won't be able to right-click the image (the area where the canvas is positioned) as opposed to the <img>
and data URIs where the user will see a long data URI when viewing the image properties panel.
这篇关于为什么浏览器在经过身份验证的 XMLHttpRequest 后不重用授权标头?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!