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

Comment rediriger avec des cookies et des en-têtes entre domaines en HTTP ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-11-02 18:30:02408parcourir

How to Redirect with Cookies and Headers Between Domains in HTTP?

Redirection d'un domaine vers un autre et définition de cookies ou d'en-têtes pour l'autre domaine

Le défi

Redirection d'un domaine à un autre avec des en-têtes personnalisés ou les cookies définis dans la réponse ne sont pas possibles en raison des limitations du protocole HTTP. Une redirection consiste essentiellement en un en-tête (Location) associé à la réponse, et elle ne permet pas d'ajouter d'en-tête à l'emplacement cible.

La configuration de cookies pour un domaine différent n'est pas non plus autorisée car cela le ferait posent un risque de sécurité important. Les navigateurs stockent les cookies envoyés par le serveur avec une réponse à l'aide de l'en-tête Set-Cookie, puis les renvoient ensuite au serveur pour les requêtes adressées au même serveur dans le même domaine. Les cookies ne sont pas envoyés vers un domaine différent.

Solution 1 : Redirection avec paramètre de requête et paramètre de cookie sur le domaine cible

Une approche consiste à demander au domaine source de rediriger l'utilisateur vers le domaine cible avec un jeton d'accès passé en paramètre de requête. Le domaine cible peut ensuite lire le jeton et définir son propre cookie, que le navigateur stockera et enverra pour les demandes ultérieures.

Domaine source (appA.py)

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

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)
    return response</code>

Domaine cible (appB.py)

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

app = FastAPI()

@app.get('/', response_class=HTMLResponse)
def home():
    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</code>

Solution 2 : communication d'origine croisée avec Window.postMessage()

Une autre approche consiste à utiliser Window. postMessage() pour la communication entre origines. Le domaine source envoie le jeton au domaine cible, qui le stocke dans localStorage et définit un cookie. Les inconvénients incluent la compatibilité du navigateur et le stockage des données sensibles dans localStorage.

Solution 3 : approche de connexion universelle StackExchange

Une solution plus robuste est utilisée par StackExchange pour la connexion automatique entre ses différents sites. Cela implique l'envoi d'un jeton d'authentification via l'attribut src d'une image, qui déclenche une réponse du serveur et définit des cookies sur le site cible.

Cela nécessite l'acceptation par le navigateur des cookies tiers et la configuration CORS sur le serveur cible. Il envoie également le jeton dans la chaîne de requête, ce qui présente des risques de sécurité potentiels.

Domaine source (appA.py)

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

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>
          <input type="button" value="Submit" onclick="submit()">
          <script>
             function submit() {
                fetch('/submit', {
                     method: 'POST',
                  })
                  .then(res => {
                     authHeader = res.headers.get('Authorization');
                     if (authHeader.startsWith(&quot;Bearer &quot;))
                        token = authHeader.substring(7, authHeader.length);
                     return res.text();
                  })
                  .then(data => {
                     var url = 'http://example.test:8001/submit?token=' + encodeURIComponent(token);
                     var img = document.createElement('img');
                     img.style = 'display:none';
                     img.crossOrigin = 'use-credentials';
                     img.onerror = function(){
                        window.location.href = 'http://example.test:8001/';
                     }
                     img.src = url;
                  })
                  .catch(error => {
                     console.error(error);
                  });
             }
          </script>
       </body>
    </html>
    '''

@app.post('/submit')
def submit():
    token = 'MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3'
    headers = {'Authorization': f'Bearer {token}'}
    response = Response('success', headers=headers)
    response.set_cookie(key='access-token', value=token, httponly=True)
    return response</code>

Domaine cible (appB .py)

<code class="python">from fastapi import FastAPI, Request, Response
from fastapi.responses import RedirectResponse
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = ['http://localhost:8000', 'http://127.0.0.1:8000',
           'https://localhost:8000', 'https://127.0.0.1:8000'] 

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=[&quot;*&quot;],
    allow_headers=[&quot;*&quot;],
)

@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.get('/submit')
def submit(request: Request, token: str):
    response = Response('success')
    response.set_cookie(key='access-token', value=token, samesite='none', secure=True, httponly=True) 
    return response</code>

Considérations de sécurité

Lors du transfert de jetons ou de la configuration de cookies entre domaines, il est crucial de prendre en compte les implications en matière de sécurité. Évitez d'envoyer des données sensibles dans la chaîne de requête car elles peuvent être interceptées ou compromises. Utilisez des connexions HTTPS pour un transfert de données sécurisé. Définissez l'indicateur SameSite sur « Aucun » avec l'indicateur Sécurisé pour la protection de l'accès entre sites.

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