Maison  >  Article  >  développement back-end  >  Comment rediriger entre les domaines et définir des cookies ou des en-têtes ?

Comment rediriger entre les domaines et définir des cookies ou des en-têtes ?

DDD
DDDoriginal
2024-10-31 05:30:01309parcourir

How to Redirect Between Domains and Set Cookies or Headers?

Comment rediriger d'un domaine à un autre et définir des cookies ou des en-têtes pour l'autre domaine ?

Comme décrit ici, vous ne pouvez pas rediriger vers un autre domaine avec des en-têtes personnalisés définis, quel que soit le langage ou le framework que vous utilisez. Une redirection dans le protocole HTTP est essentiellement un en-tête (c'est-à-dire un emplacement) associé à la réponse, et elle ne permet pas d'ajouter d'en-têtes vers l'emplacement cible. Lorsque vous ajoutez l'en-tête Authorization dans votre exemple, vous définissez essentiellement cet en-tête pour la réponse qui demande au navigateur de rediriger, et non pour la redirection elle-même. En d'autres termes, vous renvoyez cet en-tête retour au client.

Comme pour les cookies HTTP, le navigateur stocke les cookies envoyés par le serveur avec la réponse (en utilisant le Set-Cookie en-tête), puis envoie les cookies avec les requêtes faites au même serveur dans un en-tête HTTP Cookie. Selon la documentation :

L'en-tête de réponse HTTP Set-Cookie est utilisé pour envoyer un cookie du
serveur à l'agent utilisateur, afin que l'agent utilisateur puisse le renvoyer
au serveur plus tard. Pour envoyer plusieurs cookies, plusieurs en-têtes Set-Cookie
doivent être envoyés dans la même réponse.

Par conséquent, s'il s'agissait d'une redirection depuis une application (avec un sous-domaine, par exemple, abc.example.test ) à un autre (avec un sous-domaine, par exemple xyz.example.test) qui ont tous deux le même domaine (parent) (et l'indicateur de domaine a été défini sur example.test lors de la création du cookies), les cookies seraient partagés avec succès entre les deux applications (comme si le domaine était spécifié, alors les sous-domaines sont toujours inclus). Le navigateur mettra un cookie à disposition du domaine donné, y compris tous les sous-domaines, quel que soit le protocole (HTTP/HTTPS) ou le port utilisé. Vous pouvez limiter la disponibilité d'un cookie à l'aide des indicateurs de domaine et de chemin, ainsi que restreindre l'accès au cookie avec les indicateurs secure et httpOnly (voir ici et ici, ainsi que la documentation Starlette). Si l'indicateur httpOnly n'est pas défini, un attaquant potentiel peut lire et modifier les informations via JavaScript (JS), alors qu'un cookie avec l'attribut httpOnly est uniquement envoyé au serveur et est inaccessible à JS côté client.

Cependant, vous ne pouvez pas définir des cookies pour un autre domaine. Si cela était autorisé, cela présenterait une énorme faille de sécurité. Par conséquent, puisque vous "essayez de rediriger l'utilisateur d'une application (domaine) vers une autre avec un cookie défini,...*"", cela ne fonctionnerait pas, car le cookie ne sera envoyé que avec des requêtes faites au même domaine.

Solution 1

Une solution, telle que décrite ici, consiste à faire en sorte que le domaine (application) A redirige l'utilisateur vers le domaine (application) B, avec le jeton d'accès transmis dans l'URL en tant que paramètre de requête. Le domaine B lira ensuite le jeton et définira son propre cookie, de sorte que le navigateur stockera et enverra ce cookie à chaque requête ultérieure au domaine B.

Veuillez noter que vous devriez envisager d'utiliser une communication sécurisée (HTTPS). , afin que le jeton soit transféré crypté, ainsi que la définition de l'indicateur de sécurité lors de la création du cookie. Notez également que le fait d'avoir le jeton dans la chaîne de requête pose un risque de sécurité sérieux, car les données sensibles ne doivent jamais être transmises dans la chaîne de requête. En effet, la chaîne de requête, qui fait partie de l'URL, apparaît dans la barre d'adresse du navigateur ; ainsi, permettant à l'utilisateur de voir et de mettre en signet l'URL contenant le jeton (ce qui signifie qu'il est enregistré sur le disque). De plus, l'URL sera ajoutée à l'historique de navigation, ce qui signifie qu'elle sera de toute façon écrite sur le disque et apparaîtra dans l'onglet Historique (appuyez sur Ctrl H pour voir l'historique du navigateur). Les deux solutions ci-dessus permettraient aux attaquants (et aux personnes avec lesquelles vous partagez l’ordinateur/l’appareil mobile) de voler ces données sensibles. De plus, de nombreux plugins/extensions de navigateur suivent l'activité de navigation des utilisateurs : chaque URL que vous visitez est envoyée à leurs serveurs pour analyse, afin de détecter les sites Web malveillants et de vous avertir au préalable. Par conséquent, vous devez prendre en compte tout ce qui précède avant d'utiliser l'approche ci-dessous (pour les articles connexes sur ce sujet, voir ici, ici et ici).

Pour éviter d'afficher l'URL dans la barre d'adresse, l'approche ci-dessous utilise également une redirection au sein du domaine B. Une fois que le domaine B reçoit la requête vers la route /submit avec le jeton comme paramètre de requête, le domaine B répond par une redirection vers une URL nue ne contenant aucun jeton (c'est-à-dire sa page d'accueil). En raison de cette redirection, l'URL contenant le jeton ne se retrouverait pas dans l'historique de navigation. Bien que cela offre une certaine protection contre certaines attaques décrites précédemment, cela ne signifie pas que les extensions de navigateur, etc., ne pourront toujours pas capturer l'URL contenant le jeton.

Si vous testez ceci sur localhost, vous devez donner à l'application B un nom de domaine différent ; sinon, comme mentionné précédemment, les cookies seront partagés entre les applications ayant le même domaine et, par conséquent, vous finirez par recevoir les cookies définis pour le domaine A et vous ne pourrez pas savoir si l'approche fonctionne du tout. Pour ce faire, vous devez éditer le fichier /etc/hosts (sous Windows, il se trouve dans C:WindowsSystem32driversetc) et attribuer un nom d'hôte à 127.0.0.1. Par exemple :

127.0.0.1 example.test

Vous ne devez pas ajouter le schéma ou le port au domaine, ni utiliser des extensions courantes, telles que .com, .net, etc., sinon cela pourrait entrer en conflit avec l'accès à d'autres sites Web sur Internet.

Une fois que vous aurez accédé au domaine A ci-dessous, vous devrez cliquer sur le bouton de soumission pour effectuer une requête POST vers la route /submit pour démarrer la redirection. La seule raison de la requête POST est que vous l'utilisez dans votre exemple et je suppose que vous devez publier des données de formulaire. Sinon, vous pouvez également utiliser une requête GET. Dans l'application B, lors de l'exécution d'une RedirectResponse depuis une route POST (c'est-à-dire /submit) vers une route GET (c'est-à-dire /), le code d'état de la réponse devient status.HTTP_303_SEE_OTHER, comme décrit ici, ici et ici. L'application A écoute sur le port 8000, tandis que l'application B écoute sur le port 8001.

Exécutez les deux applications ci-dessous, puis accédez au domaine A à l'adresse http://127.0.0.1:8000/.

appA.py

127.0.0.1 example.test

appB.py

<code class="python">from fastapi import FastAPI, FastAPI
from fastapi.responses import RedirectResponse, HTMLResponse
import uvicorn

app = FastAPI()
           
@app.get('/', response_class=HTMLResponse)
def home():
    return """"
    <!DOCTYPE html>
    <html>
       <body>
          <h2>Click the "submit" button to be redirected to domain B</h2>
          <form method="POST" action="/submit">
             <input type="submit" value="Submit">
          </form>
       </body>
    </html>
    """
        
@app.post("/submit")
def submit():
    token = 'MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3'
    redirect_url = f'http://example.test:8001/submit?token={token}'
    response = RedirectResponse(redirect_url)
    response.set_cookie(key='access-token', value=token, httponly=True)  # set cookie for domain A too
    return response
 
if __name__ == '__main__':
    uvicorn.run(app, host='0.0.0.0', port=8000)</code>

Solution 2

Une autre solution serait d'utiliser Window.postMessage(), qui permet une communication d'origine croisée entre les objets Window ; par exemple, entre une page et une fenêtre contextuelle qu'elle a générée, ou entre une page et une iframe intégrée à celle-ci. Des exemples sur la façon d'ajouter des écouteurs d'événements et de communiquer entre les fenêtres peuvent être trouvés ici. Les étapes à suivre seraient :

Étape 1 :Ajouter au domaine A une iframe masquée au domaine B. Par exemple :

<code class="python">from fastapi import FastAPI, Request, status
from fastapi.responses import RedirectResponse
import uvicorn

app = FastAPI()

@app.get('/')
def home(request: Request):
    token = request.cookies.get('access-token')
    print(token)
    return 'You have been successfully redirected to domain B!' \
           f' Your access token ends with: {token[-4:]}'
 
@app.post('/submit')
def submit(request: Request, token: str):
    redirect_url = request.url_for('home')
    response = RedirectResponse(redirect_url, status_code=status.HTTP_303_SEE_OTHER)
    response.set_cookie(key='access-token', value=token, httponly=True)
    return response
 
if __name__ == '__main__':
    uvicorn.run(app, host='0.0.0.0', port=8001)</code>

Étape 2 :Dès que vous obtenez le jeton d'autorisation du

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn