無法使用React從Go伺服器取得cookie數據
P粉360266095
P粉360266095 2024-04-06 13:09:26
0
1
475

在 React 後我開始進入後端,並在後端伺服器上新增了 github OAUTH 和會話來保存資料。它們在後端都工作正常,我可以透過會話等從其他處理程序存取資料。但是一旦我嘗試使用 React 從後端獲取會話,我就永遠無法做到這一點。

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

我嘗試了很多東西,首先我使用了一個不同於 gorilla 的會話庫,它被稱為 scs,我想這可能是我的庫,但事實並非如此。在更改程式碼時,我得到的錯誤有所不同,但每次後端都正常運作。在來自後端的 API 請求上,有時我會得到一個空字串數據,或者網路錯誤或找不到用戶等,但每次我在程式碼後端的每次迭代中檢查後端時都工作得很好。這是獲取請求:

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

全部回覆(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 = `
  
    
    sssccc
  
`

隱身視窗無法看到其他視窗的 cookie。請檢查瀏覽器以確保 cookie 存在。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!