Mit React können keine Cookie-Daten vom Go-Server abgerufen werden
P粉360266095
P粉360266095 2024-04-06 13:09:26
0
1
578

Nach React begann ich, ins Backend einzusteigen und Github OAUTH und Sitzungen auf dem Backend-Server hinzuzufügen, um Daten zu speichern. Im Backend funktionieren sie alle einwandfrei und ich kann über Sitzungen usw. auf die Daten anderer Handler zugreifen. Aber sobald ich versuche, die Sitzung mit React vom Backend abzurufen, gelingt mir das nie mehr.

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))
}

Ich habe viele Dinge ausprobiert, zuerst habe ich eine andere Sitzungsbibliothek als Gorilla verwendet, sie heißt scs, ich dachte, es könnte meine Bibliothek sein, aber das ist nicht der Fall. Beim Ändern des Codes erhalte ich verschiedene Fehlermeldungen, aber das Backend funktioniert jedes Mal einwandfrei. Bei API-Anfragen vom Backend erhalte ich manchmal leere Zeichenfolgendaten oder einen Netzwerkfehler oder einen nicht gefundenen Benutzer usw., aber jedes Mal, wenn ich das Backend in jeder Iteration des Codes überprüfe, funktioniert es einwandfrei. Hier ist die Get-Anfrage:

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

Antworte allen(1)
P粉237029457

IIUC,网页从 http://localhost:5173 加载,并向 http://127.0.0.1:3080/user 发出 GET 请求。所以这是一个跨源请求。

默认情况下,在跨源 XMLHttpRequest 或 Fetch 调用中,浏览器不会发送凭据(例如 CookieHTTP 身份验证)。调用 XMLHttpRequest 对象或 Request 构造函数时,必须设置特定标志。

为了告诉浏览器将 cookie 发送到跨域 URL,应该像这样更改 fetch 调用:

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

有关详细信息,请参阅带有凭据的请求.

看起来后端代码已正确配置 CORS 标头,因此上述更改应该可以使其正常工作。如果没有,请检查浏览器的 DevTools 控制台。它应该包含一些错误/警告消息,告诉您出了什么问题。


这是有助于调试问题的最小演示。

  1. 启动服务器:go run main.go

  2. 在浏览器中导航至 http://127.0.0.1:3080/callback 以设置 cookie。

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

  3. 导航到 http://127.0.0.1:5173/ 打开页面。

  4. 单击此页面上的获取按钮。它应该将会话 cookie“abc”输出到 DevTools 控制台。

注释

我刚刚意识到cookie被保存到域127.0.0.1(没有端口)。所以http://127.0.0.1:5173/页面也可以读取cookie。

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 = `
  
    
    
  
`

隐身窗口无法看到其他窗口的 cookie。请检查浏览器以确保 cookie 存在。

Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage