Impossible d'obtenir les données des cookies du serveur Go à l'aide de React
P粉360266095
P粉360266095 2024-04-06 13:09:26
0
1
577

Après React, j'ai commencé à me lancer dans le backend et j'ai ajouté github OAUTH et des sessions sur le serveur backend pour enregistrer les données. Ils fonctionnent tous bien sur le backend et je peux accéder aux données d'autres gestionnaires via des sessions, etc. Mais une fois que j'essaie d'obtenir la session depuis le backend en utilisant React, je ne peux jamais le faire.

func (h Handler) HandleAuth(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "http://127.0.0.1:5173")
    w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
    w.Header().Set("Access-Control-Allow-Methods", "GET")
    url := Oauth2Config.AuthCodeURL("state", oauth2.AccessTypeOffline)
    http.Redirect(w, r, url, http.StatusFound)
}

func (h Handler) HandleAuthCallback(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "http://127.0.0.1:5173")
    w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
    w.Header().Set("Access-Control-Allow-Methods", "GET")
    code := r.URL.Query().Get("code")
    token, err := Oauth2Config.Exchange(r.Context(), code)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // Use the access token to get the user's GitHub data
    client := github2.NewTokenClient(r.Context(), token.AccessToken)
    user, _, err := client.Users.Get(r.Context(), "")
    if err != nil {
        fmt.Printf("Error: %v\n", err.Error())
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    session, err := store.Get(r, "session")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    session.Values["user"] = user.GetLogin()
    session.Values["access_token"] = token.AccessToken
    err = session.Save(r, w)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    fmt.Fprintf(w, "this is authcallback: %s", user.GetLogin())

}

func (h Handler) HandleCurrentUser(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Origin", "http://localhost:5173")
    w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
    w.Header().Set("Access-Control-Allow-Methods", "GET")
    session, err := store.Get(r, "session")
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    user, ok := session.Values["user"].(string)
    if !ok {
        http.Error(w, "Invalid user in session", http.StatusInternalServerError)
        return
    }
    // Set the content type header to JSON
    w.Header().Set("Content-Type", "text/plain")

    // Write the JSON data to the response
    w.Write([]byte(user))
}

J'ai essayé beaucoup de choses, j'ai d'abord utilisé une bibliothèque de sessions différente de celle de gorilla, elle s'appelle scs, je pensais que ça pourrait être ma bibliothèque, mais ce n'est pas le cas. Lorsque je modifie le code, j'obtiens différentes erreurs mais le backend fonctionne correctement à chaque fois. Lors des requêtes API du backend, j'obtiens parfois une chaîne de données vide, une erreur réseau ou un utilisateur introuvable, etc. mais chaque fois que je vérifie le backend à chaque itération du code, cela fonctionne correctement. Voici la demande d'obtention :

function App() {
    const [user, setUser] = useState(null);

    useEffect(() => {
        fetch('http://127.0.0.1:3080/user', {
            method: 'GET',
        })
            .then(response => response.text())
            .then(data => {
                setUser(data);
                console.log(data);
            })
            .catch(error => console.error(error));
    }, []);
[]);
    return <>
    <p>Logged in as: {user}</p>
            <button onClick={() => window.location.href = 'http://127.0.0.1:3080/oauth'}>Login</button>

    </>
}

P粉360266095
P粉360266095

répondre à tous(1)
P粉237029457

IIUC, la page Web fait une requête GET depuis http://localhost:5173 加载,并向 http://127.0.0.1:3080/user. Il s’agit donc d’une demande d’origine croisée.

Par défaut, les navigateurs n'envoient pas d'informations d'identification (telles que Cookie et Authentification HTTP) dans les appels XMLHttpRequest ou Fetch d'origine croisée. Certains indicateurs doivent être définis lors de l'appel de l'objet XMLHttpRequest ou du constructeur Request.

Pour indiquer au navigateur d'envoyer des cookies aux URL inter-domaines, l'appel de récupération doit être modifié comme ceci :

fetch('http://127.0.0.1:3080/user', {
    method: 'GET',
+   mode: 'cors',
+   credentials: 'include',
  })

Pour plus de détails, voir Demandes avec informations d'identification.

Il semble que les en-têtes CORS du code backend soient correctement configurés, les modifications ci-dessus devraient donc le faire fonctionner. Sinon, vérifiez la console DevTools de votre navigateur. Il devrait contenir des messages d'erreur/d'avertissement vous indiquant ce qui ne va pas.


Il s'agit d'une démo minimale pour aider à déboguer le problème.

  1. Démarrez le serveur : go run main.go

  2. Accédez à http://127.0.0.1:3080/callback dans votre navigateur pour définir des cookies.

    Set-Cookie: session=abc;路径=/;过期=2023 年 4 月 18 日星期二 18:34:49 GMT;最大年龄=86372;仅 Http; SameSite=Lax.

  3. Accédez à http://127.0.0.1:5173/ pour ouvrir la page.

  4. Cliquez sur le bouton Obtenir sur cette page. Il devrait afficher le cookie de session "abc" sur la console DevTools.

Remarques :

Je viens de réaliser que les cookies sont enregistrés sur le domaine 127.0.0.1 (pas de port). Ainsi, la page 127.0.0.1(没有端口)。所以http://127.0.0.1:5173/ peut également lire les cookies.

package main

import (
    "fmt"
    "net/http"
    "time"
)

func main() {
    go func() {
        _ = http.ListenAndServe(":5173", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            w.Write([]byte(page))
        }))
    }()

    http.HandleFunc("/callback", func(w http.ResponseWriter, r *http.Request) {
        http.SetCookie(w, &http.Cookie{
            Name:     "session",
            Value:    "abc",
            Path:     "/",
            Expires:  time.Now().Add(24 * time.Hour),
            MaxAge:   86372,
            HttpOnly: true,
            SameSite: http.SameSiteLaxMode,
        })
        w.Write([]byte("done"))
    })

    http.HandleFunc("/user", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin", "http://127.0.0.1:5173")
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
        w.Header().Set("Access-Control-Allow-Methods", "GET")
        w.Header().Set("Access-Control-Allow-Credentials", "true")

        cookie, err := r.Cookie("session")
        if err != nil {
            fmt.Fprintln(w, err.Error())
            return
        }
        w.Write([]byte(cookie.Value))
    })

    http.ListenAndServe(":3080", nil)
}

const page = `
  
    
    sssccc
  
`

Les fenêtres de navigation privée ne peuvent pas voir les cookies des autres fenêtres. Veuillez vérifier votre navigateur pour vous assurer que le cookie est présent.

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal