diff --git a/backend/internal/api/comments.go b/backend/internal/api/comments.go index 712d7f9..01d1d1d 100644 --- a/backend/internal/api/comments.go +++ b/backend/internal/api/comments.go @@ -10,6 +10,7 @@ import ( "encoding/hex" "errors" "net/http" + "net/url" "strconv" "strings" "time" @@ -24,6 +25,7 @@ import ( const ( readerCookie = "one_reader" oauthStateCook = "one_oauth_state" + oauthBackCook = "one_oauth_back" maxCommentLen = 500 editWindow = 10 * time.Minute ) @@ -72,6 +74,8 @@ func (a *API) authLogout(w http.ResponseWriter, r *http.Request) { // githubLogin 跳转 GitHub 授权页。state 防 CSRF 存短命 cookie; // 授权完成回到 callback 后必须带上同一个值。 +// 同时把发起登录的前台 origin 记下来(one_oauth_back), +// callback 用它跳回去——开发时前端 3000 / 后端 8080 分离才不会落错站。 func (a *API) githubLogin(w http.ResponseWriter, r *http.Request) { if !a.GH.Enabled() { httpx.NotFound(w) @@ -80,6 +84,12 @@ func (a *API) githubLogin(w http.ResponseWriter, r *http.Request) { state := randHex(16) http.SetCookie(w, &http.Cookie{Name: oauthStateCook, Value: state, Path: "/", HttpOnly: true, MaxAge: 600}) + if ref := r.Referer(); ref != "" { + if u, err := url.Parse(ref); err == nil && u.Scheme != "" && u.Host != "" { + http.SetCookie(w, &http.Cookie{Name: oauthBackCook, + Value: u.Scheme + "://" + u.Host, Path: "/", HttpOnly: true, MaxAge: 600}) + } + } http.Redirect(w, r, a.GH.LoginURL(a.Cfg.SiteURL+"/api/auth/callback/github", state), http.StatusFound) } @@ -120,7 +130,15 @@ func (a *API) githubCallback(w http.ResponseWriter, r *http.Request) { token, _ := a.ReaderSessions.Issue(reader.ID) http.SetCookie(w, &http.Cookie{Name: auth.ReaderCookie, Value: token, Path: "/", HttpOnly: true, SameSite: http.SameSiteLaxMode, MaxAge: int((30 * 24 * time.Hour).Seconds())}) - http.Redirect(w, r, "/", http.StatusFound) + // 回到发起登录的前台;没有记录(直接敲 URL 进来的)就回站点根 + back := a.Cfg.SiteURL + if ck, err := r.Cookie(oauthBackCook); err == nil && ck.Value != "" { + if u, err := url.Parse(ck.Value); err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != "" && u.Path == "" { + back = u.Scheme + "://" + u.Host + } + } + http.SetCookie(w, &http.Cookie{Name: oauthBackCook, Value: "", Path: "/", MaxAge: -1}) + http.Redirect(w, r, back, http.StatusFound) } func randHex(n int) string {