Pourquoi ne pas le navigateur de réutiliser l'autorisation des en-têtes après une authentifié XMLHttpRequest?
Je suis le développement de Single Page App à l'aide Angulaire. Le backend expose RESTE des services qui nécessitent une authentification de Base. Arriver index.html ou l'un des scripts ne nécessite pas d'authentification.
J'ai une drôle de situation où l'un de mon point de vue a un <img>
où la src
est l'url d'une API REST qui nécessite une authentification. Le <img>
est traité par le navigateur et je n'ai aucune chance de définir l'en-tête d'autorisation pour OBTENIR la demande de il fait. Qui provoque le navigateur demande d'informations d'identification.
J'ai tenté de résoudre ce problème en faisant ceci:
- Laisser
img
src
vide dans la source - Au document "prêt", faire un
XMLHttpRequest
à un service (/api/login
) avec l'Autorisation d'en-tête, juste à cause de l'authentification à se produire. - À la fin de cet appel, définissez le
img src
attribut, en pensant que d'ici là, le navigateur ne sais pour inclure l'en-tête d'Autorisation dans les requêtes suivantes...
...mais il ne le fait pas. La demande pour l'image sort sans les en-têtes. Si j'entrez les informations d'identification, puis toutes les autres images sur la page de droite.
(J'ai aussi essayé et Angulaire du ng-src
mais qui a produit le même résultat)
J'ai deux questions:
- Pourquoi ne pas le navigateur (IE10) inclure les en-têtes à toutes les demandes après un succès
XMLHttpRequest
? - Que puis-je faire pour contourner ce problème?
@bergi demandé pour les demandes d'informations. Ils sont ici.
Demande /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
Réponse (/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
Demande /utilisateur/image/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
Et puis le navigateur web de demande d'informations d'identification. Si j'entre eux, je reçois cette réponse:
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
- Pourriez-vous s'il vous plaît poster la demande envoyée et en-têtes de réponse pour le
/api/login
page et l'image? - Si vous utilisez l'authentification HTTP, tu ne peux pas manipuler la src Url à inclure le nom d'utilisateur/mot de passe comme
http://user:pass@server/path/to/img.png
? - Je ne veux pas mettre le mot de passe dans la source.
- Vous ne voulez pas mettre le mot de passe dans la source. Où voulez-vous stocker le mot de passe du navigateur (à inclure dans
XMLHttpRequest
) ethidden from view
? - Désolé, j'ai oublié d'expliquer qu'une partie. Je suis de contrôler le navigateur par le biais d'un contrôle WebBrowser hébergé dans une application écrite en C#. L'application en C# charge le navigateur index.html et transmet les informations d'identification de mon Angulaire de l'application en utilisant le javascript invocation capacités fournies par le contrôle WebBrowser. Ensuite, l'angle d'application définit comme des en-têtes par défaut sur $http.
- J'ai ajouté de la demande de détail dans ma question.
- Avez-vous de l'image relative ou absolue de la src?
- STO, c'est un parent de la src (
../api/user/picture/2218
) - Comment le mot de passe entrés? Ne pouvez-vous pas injecter le mot de passe à partir de C# dans le JS de l'environnement qui définit l'URI correct pour le
<img>
tag (http://user:pass@server
)? - Je crois que c'est à cause du fait que pas nécessairement tous de votre navigateur sont en fait des appels de REPOS. Votre navigateur ne peut pas prendre cette décision pour vous et vous devrez manuellement annonce le Http en-tête d'Autorisation. Mais je suis face au même problème que je suis de servir les images statiques
<img src='url/img.png'>
(pas par le REPOS), mais encore besoin d'une sorte d'authentification - Je ne veux pas brûler le mot de passe dans le balisage. Un utilisateur serait très peur de faire un clic droit sur une image pour copier son chemin et de voir son mot de passe en texte clair dans le lien.
- Ce qui sur le chargement des images en JS et en les injectant base64 dans le balisage? Un inconvénient si, bien entendu, que l'utilisateur verra une longue URI clic droit sur l'image et en sélectionnant "propriétés de l'Image'.
- son basic auth donc le user/pass sera toujours visible dans les en-têtes envoyer, je ne peux pas vous suffit d'inclure une image de 1x1 de la source avec le user/pass dans l'url, une fois que le royaume est authentifié votre autre demande doit juste passer
- C'est en cours d'exécution sur https uniquement si les informations d'identification dans les en-têtes sont en sécurité.
- Le chargement des images en JS et en les injectant base64 pourrait fonctionner, je suppose. Existe-il des performances, des préoccupations liées à cette approche? Si vous postez une réponse complète expliquant comment faire pour que je puisse accepter cette réponse.
- https ou pas, envoyer les en-têtes sont encore visibles à l'utilisateur du navigateur, theyre tout simplement codé sur le fil
- En effet, j'ai mal interprété votre commentaire. Je ne pense pas que l'utilisateur se soucie d'en-têtes. Je ne veux pas le partager un lien pour se faire prendre en photo sur mon système, et sans le savoir, de partager ses informations d'identification en faisant cela.
- ok à mon awnser alors, mettez une ressource avec les informations d'identification de la source et vous devriez être en jeu, j'utilise la même chose pour nos serveurs de dev
- Qu'entendez-vous par "une ressource avec les informations d'identification"?
- dans la source html: <img src="user:pass@server/1x1.gif">
- ho, je vois. Je ne suis pas encore conforme de la combustion des informations d'identification dans la page. Mais qui serait à l'œuvre (en supposant que IE prend en charge ce car ici (stackoverflow.com/questions/3823357/...), il est dit que tous les navigateurs prennent en charge cette syntaxe)
- +1 @PaulScheltema. Comme une amélioration, pas besoin de les inclure
<img src="user:pass@server/1x1.gif">
dans la source html. Il peut être ajouté dynamiquement via le script, puis l'enlever dès qu'il est chargé, encore mieux avecvisibility: hidden
ou l'équivalent. - vous pouvez charger toutes les images avec XHR jsperf.com/encoding-xhr-image-data/14
- Merci pour la référence. C'est la même solution que ce ComFreek suggéré, à droite? Je pense que je vais le faire de cette façon.
- non, il suggère de vous mettre l'image à l'encodage base64 données dans votre code html/js, par exemple. sur le serveur lire toutes les images, de les convertir à bas64, et de les rendre dans le modèle. Soit solution fonctionne, il y a quelques autres sollutions aussi, comme l'utilisation de proxy. Tout dépend de l'endroit où vous voulez résoudre, cependant, sur la question de savoir pourquoi, je ne le sais
- Merci pour la clarification.
- Une solution consisterait à faire index.html une ressource qui nécessite une autorisation (même si il est nécessaire de le sécuriser). Qui permettrait de résoudre la question sans rien de spécial.
- Les images ont besoin d'être protégés? Si non, peut-être la solution la plus simple serait de les servir séparément, sans la nécessité pour l'authentification...
- ils ont besoin d'être sécurisés.
Vous devez vous connecter pour publier un commentaire.
Idée de base
De charger les images via JavaScript et de les afficher sur le site. L'avantage est que les informations d'authentification ne sera jamais à trouver leur chemin dans le code HTML. Ils résistent à du JavaScript côté.
Étape 1: charger les données d'image via JS
Que de base de la fonctionnalité AJAX (voir aussi
XMLHttpRequest::open(méthode, uri, async, utilisateur, pw)
):Étape 2: format de données
Maintenant, comment peut-on afficher les données d'image? Lors de l'utilisation de HTML, normalement attribuer une URI de la
src
attribut de l'élément d'image. Nous pouvons appliquer le même principe ici, sauf pour le fait que nous utilisons les données Uri au lieu de "normal"http(s)://
des produits dérivés.Toile
Il y a aussi une autre option, qui consiste à peindre les données chargées dans un
<canvas>
champ. De cette façon, l'utilisateur ne sera pas en mesure de cliquer droit sur l'image (la zone où la toile est positionné), par opposition à la<img>
et les données Uri où l'utilisateur verra une longue données URI lorsque vous affichez les propriétés de l'image du panneau.overrideMimeType
(deXMLHttpRequest
). IE11 prend en charge bien. Mais je n'ai pas essayer sur IE11 que j'en ai besoin pour travailler avec IE8 et jusqu'.window.bota
est uniquement pris en charge avec IE11.Le google drive uploader est créé à l'aide d'angular js. Ses auteurs face à un problème similaire. Les icônes ont été hébergés sur un autre domaine et de le mettre comme
img src=
violé le CSP. Donc, comme vous, qu'ils étaient obligés d'aller chercher les images de l'icône à l'aide de XHR, puis en quelque sorte réussi à obtenir dans leimg
balises.Ils décrire comment ils l'ont résolu. Après l'extraction de l'image à l'aide de XHR, ils l'écrivent à l'HTML5 système de fichiers local. Ils ont mis son URL sur le système de fichiers local dans le
img
'ssrc
attribut à l'aide de lang-src
directive.Comme pour le pourquoi, je ne sais pas. Je suppose que la création d'un jeton de session pour récupérer les images est hors de question? Je m'attends à ce Cookie en-têtes ne soient envoyés? C'est une croix-origine de la demande? Dans ce cas, pouvez-vous définir le withCredentials propriété? Est-il un P3P chose, peut-être?
Une autre approche serait d'ajouter un point de fin pour vos sites de back-end qui mandaté la demande d'image. Pour que votre page pourrait demander sans informations d'identification et l'extrémité arrière serait de prendre soin de l'authentification. La fin pourrait aussi le cache de l'image si elle n'a pas changé fréquemment ou que vous saviez la fréquence avec laquelle il a été mis à jour. C'est assez facile à faire sur le back-end, rend votre frontal simple et permet d'éviter les informations d'identification d'être envoyé au navigateur.
Si le problème de l'authentification est alors le lien pourrait contenir un jeton généré pour l'utilisateur est authentifié et uniquement accessibles à partir de leur navigateur web en cours de session. Donnant accès sécurisé pour le contenu que pour l'utilisateur, il a été prévu pour et uniquement pour le temps qu'ils sont autorisés à y accéder. Cela exigerait aussi travailler dans le back-end, cependant.
Il me semble que pour résoudre votre problème, vous devez modifier la conception de votre application, au lieu d'essayer de pirater votre chemin autour de la manière dont les navigateurs fonctionnent réellement.
Une demande pour une URL sécurisée aura toujours besoin de l'authentification, au sujet de celui-ci étant effectué par le navigateur avec une balise img ou en javascript.
Si vous pouvez effectuer l'autorisation automatiquement sans interaction de l'utilisateur, vous pouvez le faire sur le côté serveur et vous n'avez pas besoin d'envoyer n'importe quel utilisateur+pass pour le client de le faire. Si c'est le cas, vous pouvez modifier le code derrière
https://myserver/dev30281_WebServices/api/user/picture/2218
de procéder à l'autorisation et à servir de l'image, sans HTTP auth, seulement si l'utilisateur est autorisé à demander, sinon, le retour d'un 403 forbidden réponse (http://en.wikipedia.org/wiki/HTTP_403).Une autre solution possible serait de séparer les pages qui contiennent les images sécurisées du reste de l'application. Donc, vous, en théorie, deux single page apps. L'utilisateur sera invité à vous identifier pour accéder à la partie sécurisée. Je n'en suis pas sûr si cela est possible dans votre cas, puisque vous n'avez pas état de toutes les exigences. Mais il fait plus de sens que si vous voulez servir d'obtenir des ressources qui nécessitent une authentification, l'utilisateur doit être invité pour les informations d'identification, tout comme le navigateur n'.
J'ai toujours analyser
Set-Cookie valeur d'en-tête dans les précédents (ou à la première demande de connexion), puis de l'envoyer de la valeur dans les prochaines demandes.
Quelque chose comme cela
Réponse après la première demande:
Toute demande suivante:
Comme vous pouvez le voir j'ai envoyer ASP.NET_SessionId="valeur" valeur en Cookie en-tête. Si le serveur utilise php, vous devez analyser PHPSESSID="une valeur"
Vous devez essayer d'utiliser le
Access-Control-Allow-Credentials: true
en-tête. Une fois, j'ai rencontré un problème avec IE qui se résumait finalement à l'utilisation de cet en-tête. Également définir$httpProvider.defaults.headers.get = { 'withCredentials' : 'true' }
dans l'angle de code js.Que pour la raison: j'ai essayé avec Chrome et Firefox, et les deux se rappeler autorisation de base seulement si le titre est entré directement à partir du Navigateur de l'INTERFACE utilisateur, c'est à dire le pop-up fait par le navigateur. Il ne se souviendra pas si le titre est venu à partir de JavaScript, bien que la requête HTTP est le même. Je suppose que c'est voulu par la conception, mais je ne le vois pas mentionné dans la norme.