MVP: 按 07 风格重写前端 + Go 后端落地(长文/短文、编辑器、后台管理)

This commit is contained in:
Sakurasan
2026-09-20 20:56:03 +08:00
parent edee708802
commit 4d8f2de3a4
96 changed files with 6005 additions and 2602 deletions
+71
View File
@@ -0,0 +1,71 @@
package admin
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"errors"
"fmt"
"strconv"
"strings"
"time"
)
// Sessions are stateless: base64("user:expiryUnix") + "." + HMAC-SHA256.
// They survive restarts as long as ONE_SECRET stays the same.
type Sessions struct {
secret []byte
ttl time.Duration
}
func NewSessions(secret string, ttl time.Duration) *Sessions {
if ttl <= 0 {
ttl = 7 * 24 * time.Hour
}
return &Sessions{secret: []byte(secret), ttl: ttl}
}
var ErrBadSession = errors.New("invalid session")
func (s *Sessions) Issue(user string) (string, time.Time) {
exp := time.Now().Add(s.ttl)
payload := base64.RawURLEncoding.EncodeToString([]byte(user + ":" + strconv.FormatInt(exp.Unix(), 10)))
return payload + "." + s.sign(payload), exp
}
func (s *Sessions) Verify(token string) (string, error) {
parts := strings.Split(token, ".")
if len(parts) != 2 {
return "", ErrBadSession
}
if !hmac.Equal([]byte(s.sign(parts[0])), []byte(parts[1])) {
return "", ErrBadSession
}
raw, err := base64.RawURLEncoding.DecodeString(parts[0])
if err != nil {
return "", ErrBadSession
}
i := strings.LastIndex(string(raw), ":")
if i <= 0 {
return "", ErrBadSession
}
user := string(raw)[:i]
expUnix, err := strconv.ParseInt(string(raw)[i+1:], 10, 64)
if err != nil {
return "", ErrBadSession
}
if time.Now().After(time.Unix(expUnix, 0)) {
return "", ErrBadSession
}
return user, nil
}
func (s *Sessions) sign(payload string) string {
mac := hmac.New(sha256.New, s.secret)
mac.Write([]byte(payload))
return base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
}
func (s *Sessions) TTL() int { return int(s.ttl.Seconds()) }
func (s *Sessions) String() string { return fmt.Sprintf("sessions(ttl=%s)", s.ttl) }