修复token过期重复调用接口

This commit is contained in:
jimleerx
2026-01-29 18:01:08 +08:00
parent e605cd07bf
commit b18116f1f6
2 changed files with 78 additions and 1 deletions

View File

@@ -138,7 +138,9 @@ func (c *Client) runWebSocket(ctx context.Context) {
defer c.wg.Done()
maxConsecutiveFailures := 5
maxAuthFailures := 10
consecutiveFailures := 0
authFailures := 0
for {
select {
@@ -156,8 +158,31 @@ func (c *Client) runWebSocket(ctx context.Context) {
return
}
// Check if this is an authentication error
if authErr, ok := err.(*AuthError); ok {
authFailures++
if authErr.IsTokenInvalid() {
log.Printf("[Agent] Authentication failed (invalid token): %v", err)
if authFailures >= maxAuthFailures {
log.Printf("[Agent] Too many auth failures (%d), entering sleep mode (30 min backoff)", authFailures)
c.waitWithTrafficReport(ctx, 30*time.Minute)
authFailures = 0
continue
}
}
// Use longer backoff for auth errors
backoff := time.Duration(authFailures) * 30 * time.Second
if backoff > 10*time.Minute {
backoff = 10 * time.Minute
}
log.Printf("[Agent] Auth error, reconnecting in %v...", backoff)
c.waitWithTrafficReport(ctx, backoff)
continue
}
log.Printf("[Agent] WebSocket error: %v", err)
consecutiveFailures++
authFailures = 0 // Reset auth failures on non-auth errors
if consecutiveFailures >= maxConsecutiveFailures {
log.Printf("[Agent] Too many WebSocket failures (%d), switching to auto mode for fallback...", consecutiveFailures)
@@ -167,6 +192,7 @@ func (c *Client) runWebSocket(ctx context.Context) {
}
} else {
consecutiveFailures = 0
authFailures = 0
}
backoff := c.calculateBackoff()
@@ -862,16 +888,23 @@ func (c *Client) getSystemNetworkStats() (rxBytes, txBytes int64) {
// AuthError represents an authentication error
type AuthError struct {
Message string
Code string // "token_expired", "token_invalid", "server_error"
}
func (e *AuthError) Error() string {
return "authentication failed: " + e.Message
}
// IsTokenInvalid returns true if the error indicates an invalid token
func (e *AuthError) IsTokenInvalid() bool {
return e.Code == "token_invalid" || e.Message == "Invalid token"
}
// WebSocket message types
const (
WSMsgTypeCertRequest = "cert_request"
WSMsgTypeCertUpdate = "cert_update"
WSMsgTypeTokenUpdate = "token_update"
)
// WSCertRequestPayload represents a certificate request from master
@@ -898,6 +931,12 @@ type WSCertUpdatePayload struct {
Error string `json:"error,omitempty"`
}
// WSTokenUpdatePayload represents a token update from master
type WSTokenUpdatePayload struct {
ServerToken string `json:"server_token"`
ExpiresAt time.Time `json:"expires_at"`
}
// handleMessage processes incoming messages from master
func (c *Client) handleMessage(conn *websocket.Conn, message []byte) {
var msg struct {
@@ -918,6 +957,13 @@ func (c *Client) handleMessage(conn *websocket.Conn, message []byte) {
return
}
go c.handleCertRequest(conn, payload)
case WSMsgTypeTokenUpdate:
var payload WSTokenUpdatePayload
if err := json.Unmarshal(msg.Payload, &payload); err != nil {
log.Printf("[Agent] Failed to parse token_update payload: %v", err)
return
}
c.handleTokenUpdate(payload)
default:
// Ignore unknown message types
}
@@ -988,3 +1034,13 @@ func (c *Client) requestCertificate(req WSCertRequestPayload) WSCertUpdatePayloa
log.Printf("[Agent] Certificate obtained for %s, expires: %s", req.Domain, certResult.ExpiryDate)
return result
}
// handleTokenUpdate processes a token update from master
func (c *Client) handleTokenUpdate(payload WSTokenUpdatePayload) {
log.Printf("[Agent] Received token update from master, new token expires at %s", payload.ExpiresAt.Format(time.RFC3339))
// Update the token in memory
c.config.Token = payload.ServerToken
log.Printf("[Agent] Token updated successfully in memory")
}

View File

@@ -1406,7 +1406,10 @@ func (h *ManageHandler) getInboundTagsFromGRPC() []string {
tags := make([]string, 0, len(resp.Inbounds))
for _, ib := range resp.Inbounds {
tags = append(tags, ib.Tag)
// 过滤掉 tag="api" 和空 tagXray 内部入站)
if ib.Tag != "" && ib.Tag != "api" {
tags = append(tags, ib.Tag)
}
}
return tags
}
@@ -1427,10 +1430,28 @@ func (h *ManageHandler) mergeInbounds(configInbounds []map[string]interface{}, r
result := make([]map[string]interface{}, 0, len(configInbounds)+len(runtimeTags))
for _, ib := range configInbounds {
tag, _ := ib["tag"].(string)
// 跳过 tag="api" 的入站Xray 内部 API 入站)
if tag == "api" {
continue
}
ibCopy := make(map[string]interface{})
for k, v := range ib {
ibCopy[k] = v
}
// 如果 tag 为空,根据协议和端口生成名称
if tag == "" {
protocol, _ := ib["protocol"].(string)
port := 0
if p, ok := ib["port"].(float64); ok {
port = int(p)
} else if p, ok := ib["port"].(int); ok {
port = p
}
if protocol != "" && port > 0 {
ibCopy["tag"] = fmt.Sprintf("%s-%d", protocol, port)
ibCopy["_generated_tag"] = true
}
}
if runtimeTagSet[tag] {
ibCopy["_runtime_status"] = "running"
} else {