fix: 修复登录401和切换机构失败 - Cookie Secure改为动态判断 + 默认邮箱修正
This commit is contained in:
@@ -20,7 +20,7 @@ import {
|
|||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
||||||
export default function LoginForm({ initialOrgs }: { initialOrgs: Organization[] }) {
|
export default function LoginForm({ initialOrgs }: { initialOrgs: Organization[] }) {
|
||||||
const [email, setEmail] = useState("fazhiribao@govai.gov.cn");
|
const [email, setEmail] = useState("fazhiwang@govai.gov.cn");
|
||||||
const [password, setPassword] = useState("admin123");
|
const [password, setPassword] = useState("admin123");
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [errorMsg, setErrorMsg] = useState("");
|
const [errorMsg, setErrorMsg] = useState("");
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ type AuthHandler struct {
|
|||||||
jwtMgr *auth.JWTManager
|
jwtMgr *auth.JWTManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isSecureCookie 根据请求协议判断是否启用 Secure 标志
|
||||||
|
// HTTPS 请求启用 Secure,HTTP(localhost 开发环境)不启用,避免浏览器拒绝 Cookie
|
||||||
|
func isSecureCookie(r *http.Request) bool {
|
||||||
|
return r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https"
|
||||||
|
}
|
||||||
|
|
||||||
func NewAuthHandler(pool *pgxpool.Pool, jwtMgr *auth.JWTManager) *AuthHandler {
|
func NewAuthHandler(pool *pgxpool.Pool, jwtMgr *auth.JWTManager) *AuthHandler {
|
||||||
return &AuthHandler{pool: pool, jwtMgr: jwtMgr}
|
return &AuthHandler{pool: pool, jwtMgr: jwtMgr}
|
||||||
}
|
}
|
||||||
@@ -100,7 +106,7 @@ func (h *AuthHandler) Register(w http.ResponseWriter, r *http.Request) {
|
|||||||
Value: tokenPair.AccessToken,
|
Value: tokenPair.AccessToken,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
Secure: true,
|
Secure: isSecureCookie(r),
|
||||||
SameSite: http.SameSiteLaxMode,
|
SameSite: http.SameSiteLaxMode,
|
||||||
MaxAge: int(24 * time.Hour / time.Second),
|
MaxAge: int(24 * time.Hour / time.Second),
|
||||||
})
|
})
|
||||||
@@ -184,7 +190,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) {
|
|||||||
Value: tokenPair.AccessToken,
|
Value: tokenPair.AccessToken,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
Secure: true,
|
Secure: isSecureCookie(r),
|
||||||
SameSite: http.SameSiteLaxMode,
|
SameSite: http.SameSiteLaxMode,
|
||||||
MaxAge: int(24 * time.Hour / time.Second),
|
MaxAge: int(24 * time.Hour / time.Second),
|
||||||
})
|
})
|
||||||
@@ -193,7 +199,7 @@ func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request) {
|
|||||||
Value: tokenPair.RefreshToken,
|
Value: tokenPair.RefreshToken,
|
||||||
Path: "/api/v1/auth/refresh",
|
Path: "/api/v1/auth/refresh",
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
Secure: true,
|
Secure: isSecureCookie(r),
|
||||||
SameSite: http.SameSiteLaxMode,
|
SameSite: http.SameSiteLaxMode,
|
||||||
MaxAge: int(7 * 24 * time.Hour / time.Second),
|
MaxAge: int(7 * 24 * time.Hour / time.Second),
|
||||||
})
|
})
|
||||||
@@ -219,7 +225,7 @@ func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) {
|
|||||||
Value: "",
|
Value: "",
|
||||||
Path: "/",
|
Path: "/",
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
Secure: true,
|
Secure: isSecureCookie(r),
|
||||||
SameSite: http.SameSiteLaxMode,
|
SameSite: http.SameSiteLaxMode,
|
||||||
MaxAge: -1,
|
MaxAge: -1,
|
||||||
})
|
})
|
||||||
@@ -228,7 +234,7 @@ func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request) {
|
|||||||
Value: "",
|
Value: "",
|
||||||
Path: "/api/v1/auth/refresh",
|
Path: "/api/v1/auth/refresh",
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
Secure: true,
|
Secure: isSecureCookie(r),
|
||||||
SameSite: http.SameSiteLaxMode,
|
SameSite: http.SameSiteLaxMode,
|
||||||
MaxAge: -1,
|
MaxAge: -1,
|
||||||
})
|
})
|
||||||
@@ -323,12 +329,32 @@ func (h *AuthHandler) SwitchOrg(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 为目标用户生成新的JWT token(通过 HttpOnly Cookie 设置)
|
// 为目标用户生成新的JWT token(通过 HttpOnly Cookie 设置)
|
||||||
_, err = h.jwtMgr.GenerateTokenPair(targetID, targetEmail, targetRole)
|
tokenPair, err := h.jwtMgr.GenerateTokenPair(targetID, targetEmail, targetRole)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.InternalError(w, "生成令牌失败")
|
response.InternalError(w, "生成令牌失败")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新 Cookie 中的 token,使切换立即生效
|
||||||
|
http.SetCookie(w, &http.Cookie{
|
||||||
|
Name: "access_token",
|
||||||
|
Value: tokenPair.AccessToken,
|
||||||
|
Path: "/",
|
||||||
|
HttpOnly: true,
|
||||||
|
Secure: isSecureCookie(r),
|
||||||
|
SameSite: http.SameSiteLaxMode,
|
||||||
|
MaxAge: int(24 * time.Hour / time.Second),
|
||||||
|
})
|
||||||
|
http.SetCookie(w, &http.Cookie{
|
||||||
|
Name: "refresh_token",
|
||||||
|
Value: tokenPair.RefreshToken,
|
||||||
|
Path: "/api/v1/auth/refresh",
|
||||||
|
HttpOnly: true,
|
||||||
|
Secure: isSecureCookie(r),
|
||||||
|
SameSite: http.SameSiteLaxMode,
|
||||||
|
MaxAge: int(7 * 24 * time.Hour / time.Second),
|
||||||
|
})
|
||||||
|
|
||||||
org := h.loadOrgInfo(r.Context(), req.OrgID)
|
org := h.loadOrgInfo(r.Context(), req.OrgID)
|
||||||
response.JSON(w, http.StatusOK, map[string]any{
|
response.JSON(w, http.StatusOK, map[string]any{
|
||||||
"message": "已切换",
|
"message": "已切换",
|
||||||
@@ -413,7 +439,7 @@ func (h *AuthHandler) Refresh(w http.ResponseWriter, r *http.Request) {
|
|||||||
Value: tokenPair.AccessToken,
|
Value: tokenPair.AccessToken,
|
||||||
Path: "/",
|
Path: "/",
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
Secure: true,
|
Secure: isSecureCookie(r),
|
||||||
SameSite: http.SameSiteLaxMode,
|
SameSite: http.SameSiteLaxMode,
|
||||||
MaxAge: int(24 * time.Hour / time.Second),
|
MaxAge: int(24 * time.Hour / time.Second),
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user