fix(cloudflare): Token 解码兼容 URL-safe base64 并发布 v1.6.6
This commit is contained in:
@@ -20,12 +20,9 @@ func DecodeToken(token string) (accountTag, tunnelID, tunnelSecret string, err e
|
||||
if clean == "" {
|
||||
return "", "", "", fmt.Errorf("token 为空")
|
||||
}
|
||||
if remainder := len(clean) % 4; remainder != 0 {
|
||||
clean += strings.Repeat("=", 4-remainder)
|
||||
}
|
||||
raw, err := base64.StdEncoding.DecodeString(clean)
|
||||
raw, err := decodeBase64(clean)
|
||||
if err != nil {
|
||||
return "", "", "", fmt.Errorf("token base64 解码失败: %w", err)
|
||||
return "", "", "", err
|
||||
}
|
||||
var payload tokenPayload
|
||||
if err := json.Unmarshal(raw, &payload); err != nil || payload.TunnelID == "" {
|
||||
@@ -45,6 +42,30 @@ func DecodeToken(token string) (accountTag, tunnelID, tunnelSecret string, err e
|
||||
return payload.AccountTag, payload.TunnelID, payload.TunnelSecret, nil
|
||||
}
|
||||
|
||||
// decodeBase64 同时兼容标准 base64 与 URL-safe base64,并兼容有无填充两种形式。
|
||||
// Cloudflare 面板生成的 Tunnel Token 使用 URL-safe 编码,直接用标准 base64 会在 '-' / '_' 处失败。
|
||||
func decodeBase64(input string) ([]byte, error) {
|
||||
encodings := []*base64.Encoding{
|
||||
base64.StdEncoding, base64.RawStdEncoding,
|
||||
base64.URLEncoding, base64.RawURLEncoding,
|
||||
}
|
||||
for _, encoding := range encodings {
|
||||
if data, err := encoding.DecodeString(input); err == nil {
|
||||
return data, nil
|
||||
}
|
||||
}
|
||||
padded := input
|
||||
if remainder := len(padded) % 4; remainder != 0 {
|
||||
padded += strings.Repeat("=", 4-remainder)
|
||||
}
|
||||
for _, encoding := range encodings {
|
||||
if data, err := encoding.DecodeString(padded); err == nil {
|
||||
return data, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("token base64 解码失败:请确认粘贴的是完整的 Cloudflare 隧道 token")
|
||||
}
|
||||
|
||||
// CredentialsJSON 生成 cloudflared 需要的 creds.json 内容。
|
||||
func CredentialsJSON(accountTag, tunnelID, tunnelSecret string) string {
|
||||
data, _ := json.MarshalIndent(map[string]string{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cloudflared
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -32,6 +33,28 @@ func TestDecodeTokenRejectsInvalid(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeTokenURLSafe(t *testing.T) {
|
||||
payload := `{"a":"account-1","t":"tunnel-2","s":"secret-3"}`
|
||||
encoded := base64.RawURLEncoding.EncodeToString([]byte(payload))
|
||||
if _, _, _, err := DecodeToken(encoded); err != nil {
|
||||
t.Fatalf("URL-safe token 应可解码: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeBase64Flexible(t *testing.T) {
|
||||
raw := []byte{0xfb, 0xef, 0xbe, 0xad}
|
||||
for _, encoded := range []string{
|
||||
base64.RawURLEncoding.EncodeToString(raw),
|
||||
base64.URLEncoding.EncodeToString(raw),
|
||||
base64.RawStdEncoding.EncodeToString(raw),
|
||||
} {
|
||||
got, err := decodeBase64(encoded)
|
||||
if err != nil || !bytes.Equal(got, raw) {
|
||||
t.Fatalf("编码 %q 解码失败:%v", encoded, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildIngressInvariants(t *testing.T) {
|
||||
got := BuildIngress([]string{"B.example.com", "a.example.com", "a.example.com", " "}, "http://127.0.0.1:80")
|
||||
if len(got) != 3 {
|
||||
|
||||
Reference in New Issue
Block a user