私はAngularを使用してシングルページアプリを開発しています。バックエンドは、基本認証を必要とするRESTサービスを公開します。index.htmlまたはスクリプトのいずれかを取得するために認証は必要ありません。
私のビューの1つに<img>
があり、src
がREST認証を必要とするAPIのURLです。<img>
はブラウザによって処理され、それが行うGETリクエストの認証ヘッダーを設定する機会がありません。
私はこれを行うことでこれを修正しようとしました:
img
src
を空のままにしますXMLHttpRequest
をサービス(/api/login
)に作成します。img src
属性を設定します。それまでに、ブラウザーは後続のリクエストにAuthorizationヘッダーを含めることを知っていると思います......しかし、そうではありません。画像のリクエストはヘッダーなしで送信されます。資格情報を入力すると、ページ上の他のすべての画像が正しくなります。 (Angularのng-src
も試しましたが、同じ結果になりました)
2つの質問があります。
XMLHttpRequest
の成功後にすべてのリクエストにヘッダーを含めなかったのはなぜですか?@ bergiはリクエストの詳細を尋ねました。ここにあります。
/ 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)
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
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を使用する場合、通常はURIを画像要素のsrc
属性に割り当てます。ここでは、 'normal' http(s)://
派生物の代わりに data URIs を使用するという事実を除いて、同じ原則を適用できます。
_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>
_フィールドにペイントすることで構成される別のオプションもあります。この方法では、ユーザーは、画像を表示するときに長いデータURIが表示される_<img>
_およびデータURIとは対照的に、画像(キャンバスが配置されている領域)を右クリックできません。プロパティパネル。
Googleドライブアップローダーはangular js。を使用して作成されます。作成者は同様の問題に直面しました。アイコンは別のドメインでホストされ、_img src=
_としてCSPに違反しています。あなたは、XHRを使用してアイコン画像を取得し、なんとかしてそれらをimg
タグに入れる必要がありました。
解決方法を説明してください 。 XHRを使用して画像を取得した後、HTML5ローカルファイルシステムに書き込みます。 _ng-src
_ ディレクティブを使用して、URLをimg
の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のものですか?
もう1つのアプローチは、イメージリクエストをプロキシしたサイトバックエンドにエンドポイントを追加することです。したがって、ページは資格情報なしでそれを要求でき、バックエンドが認証を処理します。バックエンドは、頻繁に変更されなかった場合、または更新の頻度がわかっていた場合、イメージをキャッシュすることもできます。これはバックエンドで行うのが非常に簡単で、フロントエンドをシンプルにし、資格情報がブラウザに送信されるのを防ぎます。
問題が認証の場合、リンクには、認証され、現在のブラウザーセッションからのみアクセス可能なユーザー用に生成された単一使用トークンが含まれる場合があります。コンテンツへの安全なアクセスを許可するのは、それが意図されたユーザーに対してのみであり、アクセスが許可されている時間のみです。ただし、これにはバックエンドでの作業も必要になります。
Access-Control-Allow-Credentials: true
ヘッダーを使用してみてください。私はかつてIEの問題に遭遇しました。これは最終的にこのヘッダーの使用に要約されました。また、angular jsコードで$httpProvider.defaults.headers.get = { 'withCredentials' : 'true' }
.
私はいつも解析する
Set-Cookie前の(または最初のログイン要求)のヘッダー値を指定し、次の要求でその値を送信します。
このようなもの
最初の要求後の応答:
Date:Thu, 26 Dec 2013 16:20:53 GMT
Expires:-1
Pragma:no-cache
Set-Cookie:ASP.NET_SessionId=lb1nbxeyfhl5suii2hfchxpx; domain=.example.com; path=/; secure; HttpOnly
Vary:Accept-Encoding
X-Cdn:Served-By-Akamai
X-Powered-By:ASP.NET
次のリクエスト:
Accept:text/html,application/xhtml+xml
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8,ru;q=0.6
Cache-Control:no-cache
Connection:keep-alive
Cookie:ASP.NET_SessionId=lb1nbxeyfhl5suii2hfchxpx;
ご覧のとおり、ASP.NET_SessionId = "any value"の値をCookieヘッダーで送信します。サーバーがphpを使用する場合、PHPSESSID = "some value"を解析する必要があります
理由として:私はChromeとFirefoxを試しましたが、両方とも基本的な承認を覚えていますのみ資格情報が入力されますブラウザUIから直接、つまり、ブラウザによって作成されたポップアップです。HTTPリクエストは同じですが、資格情報がJavaScriptからのものである場合は記憶されません。これは仕様によるものですが、標準では言及されていません。