开源前加固认证与部署契约:加密随机 JWT、改密事务吊销、登录 CSRF,并禁止生产回落 localhost。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -59,27 +59,46 @@ func setAuthCookies(c *gin.Context, accessToken, refreshToken string, secure boo
|
||||
})
|
||||
}
|
||||
|
||||
// clearAuthCookies 清除当前契约下的三枚认证 cookie(名称随 ConfigureCookieNames,Path=/)。
|
||||
// clearAuthCookies 清除当前契约下的认证 cookie,并顺带清历史 Path=/api/auth 与无前缀名。
|
||||
func clearAuthCookies(c *gin.Context, secure bool) {
|
||||
cookies := []struct {
|
||||
type ck struct {
|
||||
name string
|
||||
httpOnly bool
|
||||
}{
|
||||
}
|
||||
cookies := []ck{
|
||||
{service.CookieName, true},
|
||||
{service.RefreshCookieName, true},
|
||||
{service.CSRFCookieName, false},
|
||||
// 历史无 __Host- 前缀(切换 DEV_MODE 后避免双 cookie)
|
||||
{"j13_token", true},
|
||||
{"j13_refresh", true},
|
||||
{"j13_csrf", false},
|
||||
{"__Host-j13_token", true},
|
||||
{"__Host-j13_refresh", true},
|
||||
{"__Host-j13_csrf", false},
|
||||
}
|
||||
paths := []string{"/", "/api/auth"}
|
||||
for _, ck := range cookies {
|
||||
http.SetCookie(c.Writer, &http.Cookie{
|
||||
Name: ck.name,
|
||||
Value: "",
|
||||
Path: "/",
|
||||
MaxAge: -1,
|
||||
HttpOnly: ck.httpOnly,
|
||||
Secure: secure,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
Expires: time.Unix(0, 0),
|
||||
})
|
||||
for _, path := range paths {
|
||||
// __Host- 要求 Secure=true 且 Path=/;非 / 路径跳过 Host 前缀名
|
||||
if strings.HasPrefix(ck.name, "__Host-") && path != "/" {
|
||||
continue
|
||||
}
|
||||
sec := secure
|
||||
if strings.HasPrefix(ck.name, "__Host-") {
|
||||
sec = true
|
||||
}
|
||||
http.SetCookie(c.Writer, &http.Cookie{
|
||||
Name: ck.name,
|
||||
Value: "",
|
||||
Path: path,
|
||||
MaxAge: -1,
|
||||
HttpOnly: ck.httpOnly,
|
||||
Secure: sec,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
Expires: time.Unix(0, 0),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,7 +252,7 @@ func (h *Handlers) Refresh(c *gin.Context) {
|
||||
// access JWT 无状态、15 分钟自然过期;登出后 tv 不递增,属可接受的短窗口。
|
||||
func (h *Handlers) Logout(c *gin.Context) {
|
||||
if refreshToken, err := c.Cookie(service.RefreshCookieName); err == nil && refreshToken != "" {
|
||||
h.Auth.RevokeRefreshToken(refreshToken)
|
||||
_ = h.Auth.RevokeRefreshToken(refreshToken)
|
||||
}
|
||||
clearAuthCookies(c, !h.Cfg.DevMode)
|
||||
c.JSON(http.StatusOK, gin.H{"message": "已登出"})
|
||||
|
||||
Reference in New Issue
Block a user