Files
silk/server-go/internal/ws/ticket.go
T
2026-08-14 00:45:22 +08:00

58 lines
1.1 KiB
Go

package ws
import (
"crypto/rand"
"encoding/hex"
"net/url"
"time"
)
const wsTicketTTL = 60 * time.Second
type wsTicket struct {
userID string
username string
role string
expiresAt time.Time
used bool
}
// IssueTicket 签发一次性 WebSocket ticket,避免长期 JWT 进入 URL。
func (h *Hub) IssueTicket(userID, username, role string) string {
buf := make([]byte, 32)
if _, err := rand.Read(buf); err != nil {
return ""
}
ticket := hex.EncodeToString(buf)
h.ticketsMu.Lock()
h.tickets[ticket] = &wsTicket{
userID: userID,
username: username,
role: role,
expiresAt: time.Now().Add(wsTicketTTL),
}
h.ticketsMu.Unlock()
return ticket
}
func (h *Hub) consumeTicket(ticket string) (wsTicket, bool) {
h.ticketsMu.Lock()
defer h.ticketsMu.Unlock()
info, ok := h.tickets[ticket]
if !ok || info.used || time.Now().After(info.expiresAt) {
return wsTicket{}, false
}
info.used = true
return *info, true
}
func (h *Hub) ticketFromQuery(rawQuery string) string {
values, err := url.ParseQuery(rawQuery)
if err != nil {
return ""
}
return values.Get("ticket")
}