66 lines
1.8 KiB
Go
66 lines
1.8 KiB
Go
package server
|
||
|
||
import (
|
||
"crypto/hmac"
|
||
"crypto/rand"
|
||
"crypto/sha256"
|
||
"encoding/base64"
|
||
"encoding/json"
|
||
"errors"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
// SRS 推流 JWT(HS256)。服务端签发、并在 WHIP 反代层校验 role=publish,
|
||
// 形成「分发入口」的访问控制。Cloudflare 走自身 AppSecret,无需此 token。
|
||
func b64url(b []byte) string { return base64.RawURLEncoding.EncodeToString(b) }
|
||
|
||
type streamClaims struct {
|
||
Room string `json:"room"`
|
||
Identity string `json:"identity"`
|
||
Role string `json:"role"`
|
||
Exp int64 `json:"exp"`
|
||
Iat int64 `json:"iat"`
|
||
}
|
||
|
||
func signStreamToken(secret, room, identity, role string, ttl time.Duration) (string, error) {
|
||
now := time.Now()
|
||
c := streamClaims{Room: room, Identity: identity, Role: role, Iat: now.Unix(), Exp: now.Add(ttl).Unix()}
|
||
payload, _ := json.Marshal(c)
|
||
header, _ := json.Marshal(map[string]string{"alg": "HS256", "typ": "JWT"})
|
||
signing := b64url(header) + "." + b64url(payload)
|
||
mac := hmac.New(sha256.New, []byte(secret))
|
||
mac.Write([]byte(signing))
|
||
return signing + "." + b64url(mac.Sum(nil)), nil
|
||
}
|
||
|
||
func verifyStreamToken(secret, token string) (*streamClaims, error) {
|
||
parts := strings.Split(token, ".")
|
||
if len(parts) != 3 {
|
||
return nil, errors.New("bad token")
|
||
}
|
||
mac := hmac.New(sha256.New, []byte(secret))
|
||
mac.Write([]byte(parts[0] + "." + parts[1]))
|
||
if !hmac.Equal([]byte(b64url(mac.Sum(nil))), []byte(parts[2])) {
|
||
return nil, errors.New("bad signature")
|
||
}
|
||
p, err := base64.RawURLEncoding.DecodeString(parts[1])
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
var c streamClaims
|
||
if err := json.Unmarshal(p, &c); err != nil {
|
||
return nil, err
|
||
}
|
||
if c.Exp < time.Now().Unix() {
|
||
return nil, errors.New("token expired")
|
||
}
|
||
return &c, nil
|
||
}
|
||
|
||
func randomID() string {
|
||
b := make([]byte, 9)
|
||
rand.Read(b)
|
||
return base64.RawURLEncoding.EncodeToString(b)
|
||
}
|