优化结构

This commit is contained in:
Yvan
2026-08-24 21:50:33 +08:00
parent d3c20c578f
commit 969afee284
20 changed files with 497 additions and 244 deletions
+14 -6
View File
@@ -7,6 +7,7 @@ import (
"net/http"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
"golang.org/x/sync/singleflight"
@@ -14,6 +15,10 @@ import (
const claimsKey = "admin_claims"
// tokenAuthTimeout bounds a shared token authentication flight. It replaces the
// leader request's own deadline, which followers must not inherit.
const tokenAuthTimeout = 10 * time.Second
var refreshTokens singleflight.Group
type TokenAuthenticator interface {
@@ -36,7 +41,7 @@ func AuthenticateWebSocket(c *gin.Context, auth TokenAuthenticator) bool {
}
func authenticate(c *gin.Context, auth TokenAuthenticator, allowQueryToken bool) bool {
token := requestToken(c, allowQueryToken)
token := RequestToken(c, allowQueryToken)
if token == "" {
NoAuth(c, "未登录或非法访问,请登录")
return false
@@ -45,8 +50,15 @@ func authenticate(c *gin.Context, auth TokenAuthenticator, allowQueryToken bool)
NoAuth(c, "认证服务不可用")
return false
}
// Followers of a singleflight flight must not inherit the leader's request
// context: if the leader's client disconnects mid-flight, its cancellation
// would surface as an auth failure for every follower and force-log-out
// unrelated sessions. Detach cancellation and bound the shared call with an
// explicit timeout instead.
value, err, _ := refreshTokens.Do(token, func() (any, error) {
return auth.AuthenticateToken(c.Request.Context(), token)
ctx, cancel := context.WithTimeout(context.WithoutCancel(c.Request.Context()), tokenAuthTimeout)
defer cancel()
return auth.AuthenticateToken(ctx, token)
})
if err != nil {
SetTokenCookie(c, "", -1)
@@ -93,10 +105,6 @@ func RequestToken(c *gin.Context, allowQueryToken bool) string {
return token
}
func requestToken(c *gin.Context, allowQueryToken bool) string {
return RequestToken(c, allowQueryToken)
}
func tokenErrorMessage(err error) string {
message := "无法处理此token"
switch {