Documentation
¶
Overview ¶
Package webhook webhook 签约原语族:「收」(验签)与「发」(签名)两侧 的字段约定单源。
收侧(验签原语族,#270) ¶
验证器接口 + HMAC 家族(sha256/384/512 多算法、hex/base64 多编码、可选 前缀、header 回退链)+ 时间戳防重放 HMAC + 静态令牌 + 回退组合子 + per-platform 注册表。收编自 go-git-platform provider/webhook.go 的五个 验签器形态(GitHub sha256=<hex> 双形态 / Forgejo·Gitea 双 header 回退 / GitCode 签名+静态令牌双模 / Gitee 时间戳+密钥 HMAC-base64 含时间漂移 防重放 / 任意算法任意 header 的泛型形态),下游可整文件删除私有实现。
服务端把 body 读成 []byte 后传进来(框架各异,读体不是原语的职责):
v := webhook.NewGitHubValidator(secret)
if err := v.Validate(r, body); err != nil { ... }
实现纪律(每条都是现场教训,逐条搬进源码):
- **常量时间比较**:全部签名/令牌比对走 crypto/hmac.Equal——普通 bytes.Equal 有时序侧信道,攻击者可逐字节爆破签名;
- **空密钥 fail-closed**:构造期空 secret 直接 panic(「空密钥使 HMAC 验证对可预测载荷形同虚设」)——与 StaticToken 同口径,绝无 「没配密钥就静默放行」的降级路径;
- **签名解码双形态**:GitHub 带 sha256= 前缀、部分平台裸 hex/base64 ——剥离可配前缀(大小写不敏感)后统一解码;
- **双 header 回退**:分叉平台的 header 约定漂移(Forgejo 老版本用 Gitea 的 header)——header 链按序消歧,「谁在用谁」的约定写进 平台构造器;
- **多模消歧的优先序**:签名模式优先于密码模式(Fallback 组合子的 语义保证:签名 header 在场即裁决、错签硬失败不降级;仅当签名 header 缺席才落到密码/静态令牌模式)——防同 secret 交叉认证。
收侧错误语义(errors.Is 判定):
- ErrMissingSignature:验签 header 整体缺席——Fallback 据此落下一 个候选模式,调用方一般视作「非本平台/未配签名」拒绝;
- ErrBadSignature:签名在场但不匹配(含解码失败)——硬失败;
- ErrStaleTimestamp:时间戳缺席/非法/超出容忍窗——硬失败(防重放);
- ErrUnknownPlatform:注册表查无此平台。
发侧(签名原语族,#325/#328) ¶
验签族的对称面:任何往外发 webhook 的服务(事件转发器、平台对端)与 每个测 webhook 接收的测试夹具,都不必再手算 HMAC——签名 message 形态 (hmacSum)、前缀/编码(encodeSignature,与收侧 decodeSignature 镜像)、 平台 header 名与收侧共用同一份实现,「发」与「收」的字段约定没有第二源, 跨服务对接时两侧字段对不上的事故面从源头消除。
HMACSigner 是 HMACValidator 的逐参数对偶(同 secret 同选项下互逆); TimestampHMACSigner 是 TimestampHMACValidator 的对偶(发出时打时间戳); SignHMAC / SignTimestampHMAC 是两条纯函数 helper(测试夹具一行替代手写 hmac 块);NewEventID + EventEnvelope 给出幂等事件 ID 与标准事件信封的 推荐形态。边界哲学与收侧一致:Sign 只产出可直接套上出站请求的 header 集、 信封只产出 payload 字节,HTTP 发送归调用方——纯函数零状态,不读体不发送。
发出侧 ↔ 收侧配对表(同 secret 下 Sign 喂 Validate 必过,配对测试钉住):
发出侧 收侧 NewGitHubStyleSigner NewGitHubValidator NewForgejoSigner NewForgejoValidator NewGiteaSigner NewGiteaValidator NewGitCodeSigner NewGitCodeValidator NewGiteeSigner NewGiteeValidator SignHMAC / NewHMACSigner NewHMACValidator(同组选项同配) SignTimestampHMAC / NewTimestampHMACSigner NewTimestampHMACValidator
注意事项(与收侧纪律成对):secret 空串同样 panic fail-closed(无密钥 签名等于裸奔);前缀/编码/message 组装在两侧必须**同配**(发侧带 sha256= 前缀、收侧没配剥前缀 = 无故拒绝,配对表与同组选项就是为了把 这类联调事故挡在构造期);SignerWith* 是发侧选项前缀,与收侧 With* 一一对应成对。
本包只做「签」与「验」,不读请求体/不判 IP 白名单/不解析事件类型/不发 请求——时间戳防重放窗的判定在收端,发出端只负责按约定打出时间戳与 幂等 ID(消费端按 DefaultDeliveryHeader 去重)。
Index ¶
- Constants
- Variables
- func NewEventID(producer, event string) (string, error)
- func SignHMAC(secret []byte, algo crypto.Hash, payload []byte, opts ...HMACOption) string
- func SignTimestampHMAC(secret []byte, algo crypto.Hash, ts string) string
- type EventEnvelope
- type HMACOption
- type HMACSigner
- func NewForgejoSigner(secret []byte) *HMACSigner
- func NewGitCodeSigner(secret []byte) *HMACSigner
- func NewGitHubStyleSigner(secret []byte) *HMACSigner
- func NewGiteaSigner(secret []byte) *HMACSigner
- func NewHMACSigner(secret []byte, algo crypto.Hash, header string, opts ...HMACSignerOption) *HMACSigner
- type HMACSignerOption
- func SignerWithBase64() HMACSignerOption
- func SignerWithClock(now func() time.Time) HMACSignerOption
- func SignerWithDeliveryID(fn func() string) HMACSignerOption
- func SignerWithEvent(event string) HMACSignerOption
- func SignerWithProducer(producer string) HMACSignerOption
- func SignerWithSignaturePrefix(prefix string) HMACSignerOption
- func SignerWithTimestampHeader(name string) HMACSignerOption
- type HMACValidator
- type Registry
- type Signer
- type StaticTokenValidator
- type TimestampHMACSigner
- type TimestampHMACValidator
- type TimestampOption
- type TimestampSignerOption
- type Validator
- type ValidatorFunc
Constants ¶
const ( // DefaultEventHeader 事件类型头(Sign 在配置了事件类型时写入)。 DefaultEventHeader = "X-Webhook-Event" // DefaultDeliveryHeader 幂等投递 ID 头(Sign 写入,值形如 // <producer>-<event>-<uuidv4>,见 NewEventID)。 DefaultDeliveryHeader = "X-Webhook-Delivery" // DefaultTimestampHeader 发出时间戳头(SignerWithTimestampHeader 开启 // 时写入,unix 秒;收端可用 NewHMACValidator 同头自取或另行校验防重放窗)。 DefaultTimestampHeader = "X-Webhook-Timestamp" )
发出侧推荐约定头名(#328 设计点 2):通用发端服务用推荐名(与 GitHub 的 X-GitHub-Event/X-GitHub-Delivery 同风格),平台历史名随平台构造器走。 验签侧没有这些头的既定约定,用泛型验证器按名取即可。
const DefaultMaxDrift = time.Hour
DefaultMaxDrift 时间戳容忍窗缺省(Gitee 官方文档:与请求调用时间误差 不能超过 1 小时)。
Variables ¶
var ( // ErrMissingSignature 验签 header 整体缺席。Fallback 组合子据此落到 // 下一个候选模式;到达调用方时一般视作「非本平台/未配签名」拒绝。 ErrMissingSignature = errors.New("webhook: 验签 header 缺失") // ErrBadSignature 签名在场但不匹配(含前缀不符、编码解码失败)—— // 硬失败,绝不降级到其他模式(防同 secret 交叉认证)。 ErrBadSignature = errors.New("webhook: 签名不匹配") // ErrStaleTimestamp 时间戳缺席、非法或超出容忍窗——防重放硬失败。 ErrStaleTimestamp = errors.New("webhook: 时间戳缺失/非法/超出容忍窗") // ErrUnknownPlatform 注册表查无此平台。 ErrUnknownPlatform = errors.New("webhook: 平台未注册") )
验签错误哨兵(errors.Is 判定;语义见包文档)。
Functions ¶
func NewEventID ¶ added in v0.42.0
NewEventID 推荐幂等事件 ID 形态(#328 设计点 2):<producer>-<event>- <uuidv4>(空段跳过——没有 producer 就是 <event>-<uuid>)。uuidv4 取自 crypto/rand(pkg 零第三方依赖,不引 uuid 库)。随机源失败显式上抛 (仓规总则③)——降级成时间戳 ID 会让重试窗口内的重发无法被识别为同一次投递。
Types ¶
type EventEnvelope ¶ added in v0.42.0
type EventEnvelope struct {
Event string `json:"event"`
ID string `json:"id"`
Timestamp int64 `json:"timestamp"` // Unix 秒
Data json.RawMessage `json:"data"`
}
EventEnvelope 事件信封:Data 内嵌原始 payload(json.RawMessage,字节原 样嵌入不重排序)。字段导出——调用方可直接构造(时间戳可注入固定值做 确定性测试),NewEventEnvelope 是 fail-fast 快捷口。
func NewEventEnvelope ¶ added in v0.42.0
func NewEventEnvelope(event, id string, payload []byte) *EventEnvelope
NewEventEnvelope 构造事件信封(Timestamp 取当前时刻)。
event/id 空串、payload 空、payload 不是合法 JSON 均为构造期配置错误, panic fail-fast(信封的 event/id 是消费端路由与幂等去重的键,缺了等于 没信封;payload 非法 JSON 会在消费端炸出难排查的解码错,不如产出期就死)。
func (*EventEnvelope) Bytes ¶ added in v0.42.0
func (e *EventEnvelope) Bytes() ([]byte, error)
Bytes 信封的线格式字节(json.Marshal)——签名器与 HTTP 发送吃的就是它。
type HMACOption ¶
type HMACOption func(*HMACValidator)
HMACOption HMACValidator 的构造选项(仓规禁裸 Option)。
func WithBase64 ¶
func WithBase64() HMACOption
WithBase64 签名值按 base64(std)解码;缺省 hex。Gitee 家族是 base64、 GitHub/Forgejo/Gitea/GitCode 家族是 hex——按平台约定显式声明。
func WithFallbackHeaders ¶
func WithFallbackHeaders(names ...string) HMACOption
WithFallbackHeaders 主 header 缺席时的回退 header(按序消歧——分叉平台 的 header 约定漂移:Forgejo 老版本用 Gitea 的 header,「谁在用谁」由 调用方按序声明)。重复声明主 header 不去重(无害:命中即停)。
func WithSignaturePrefix ¶
func WithSignaturePrefix(prefix string) HMACOption
WithSignaturePrefix 签名值前缀(如 GitHub 的 "sha256="):比对时大小写 不敏感地剥离;前缀在场但不匹配时**不剥离**、交由裸解码失败拒绝—— fail-closed(sha1= 的旧签名喂给 sha256 验签器必须死,不能当裸 hex 活)。
type HMACSigner ¶ added in v0.42.0
type HMACSigner struct {
// contains filtered or unexported fields
}
HMACSigner HMACValidator 的发出侧对偶:签名值 = prefix + enc(hmac(algo, key=secret, message=payload)),与 NewHMACValidator 同语义面逐字节互逆 ——同 secret 同选项下 Sign 产出的 header 喂给 Validate 必过(配对表 测试钉住)。可选附带事件类型头、幂等投递 ID 头与时间戳头(推荐约定, 见 SignerWithEvent / SignerWithTimestampHeader)。
func NewForgejoSigner ¶ added in v0.42.0
func NewForgejoSigner(secret []byte) *HMACSigner
NewForgejoSigner Forgejo 形态发出侧:X-Forgejo-Signature,裸 hex——与 NewForgejoValidator 同款(收端自带 X-Gitea-Signature 回退,发端只写 主 header)。
func NewGitCodeSigner ¶ added in v0.42.0
func NewGitCodeSigner(secret []byte) *HMACSigner
NewGitCodeSigner GitCode 形态发出侧:X-GitCode-Signature,裸 hex——与 NewGitCodeValidator 的签名模式同款。静态令牌模式没有「生成」面(令牌 是明文常量,发出就是 req.Header.Set("X-GitCode-Token", token) 一行), 不设对应构造器。
func NewGitHubStyleSigner ¶ added in v0.42.0
func NewGitHubStyleSigner(secret []byte) *HMACSigner
NewGitHubStyleSigner GitHub 形态发出侧:X-Hub-Signature-256,值 sha256=<hex>——与 NewGitHubValidator 同款形态。
func NewGiteaSigner ¶ added in v0.42.0
func NewGiteaSigner(secret []byte) *HMACSigner
NewGiteaSigner Gitea 形态发出侧:X-Gitea-Signature,裸 hex——与 NewGiteaValidator 同款。
func NewHMACSigner ¶ added in v0.42.0
func NewHMACSigner(secret []byte, algo crypto.Hash, header string, opts ...HMACSignerOption) *HMACSigner
NewHMACSigner 构造泛型 HMAC 签名器——NewHMACValidator 的逐参数对偶。
构造校验与验签器同口径:secret 为空 panic fail-closed(发出的签名没有 密钥等于裸奔,宁可不发);algo 白名单同 NewHMACValidator;header 空串 panic;nil 选项 panic。
func (*HMACSigner) Sign ¶ added in v0.42.0
func (s *HMACSigner) Sign(payload []byte) (http.Header, error)
Sign 签出已签 payload 的 header 集:
- 签名头(构造参数 header):prefix + enc(hmac(algo, key=secret, message=payload))——与 NewHMACValidator 同选项下逐字节互逆;
- 时间戳头(SignerWithTimestampHeader 开启时):unix 秒;
- 事件头 + 幂等投递 ID 头(SignerWithEvent 配置时):DefaultEventHeader / DefaultDeliveryHeader,ID 走 NewEventID 推荐形态或 SignerWithDeliveryID。
返回的 header 可直接套到出站请求(h := signed.Header(); req.Header = h 或逐个 req.Header.Set),调用方可在其上继续追加自有头。error 仅在幂等 ID 的随机源失败(crypto/rand 读失败)时非 nil。
type HMACSignerOption ¶ added in v0.42.0
type HMACSignerOption func(*HMACSigner)
HMACSignerOption HMACSigner 的构造选项(发出侧选项统一 SignerWith* 前缀, 与验签侧的 With* 一一对应成对)。
func SignerWithBase64 ¶ added in v0.42.0
func SignerWithBase64() HMACSignerOption
SignerWithBase64 签名值按 base64(std)编码;缺省 hex——与验签侧 WithBase64 同语义,两侧必须同配。
func SignerWithClock ¶ added in v0.42.0
func SignerWithClock(now func() time.Time) HMACSignerOption
SignerWithClock 时钟注入(假时钟确定性测试;与 cache.RunWithClock 同纪律)。
func SignerWithDeliveryID ¶ added in v0.42.0
func SignerWithDeliveryID(fn func() string) HMACSignerOption
SignerWithDeliveryID 自定义投递 ID 生成器(已有分布式 ID 的服务接入用; 缺省走 NewEventID 推荐形态)。fn 返回空串视为配置错误——空 ID 使消费端 幂等去重失效,Sign 时 panic 而非发出。
func SignerWithEvent ¶ added in v0.42.0
func SignerWithEvent(event string) HMACSignerOption
SignerWithEvent 声明事件类型:Sign 写入 DefaultEventHeader,并连带写入 DefaultDeliveryHeader 幂等投递 ID。event 为空串是配置错误(事件类型是 幂等 ID 推荐形态的组成部分),panic。
func SignerWithProducer ¶ added in v0.42.0
func SignerWithProducer(producer string) HMACSignerOption
SignerWithProducer 幂等投递 ID 升级为推荐完整形态 <producer>-<event>- <uuidv4>(#328 设计点 2)——跨服务对账时 producer 段区分「谁发的」, 同 event 名的服务不会撞 ID。producer 为空串是配置错误,panic。
func SignerWithSignaturePrefix ¶ added in v0.42.0
func SignerWithSignaturePrefix(prefix string) HMACSignerOption
SignerWithSignaturePrefix 签名值前缀(如 GitHub 的 "sha256=")——与验签 侧 WithSignaturePrefix 同语义:两侧必须同配,否则验签端剥不掉前缀 (带前缀值喂给无前缀验证器会被裸解码拒绝)。
func SignerWithTimestampHeader ¶ added in v0.42.0
func SignerWithTimestampHeader(name string) HMACSignerOption
SignerWithTimestampHeader 开启发出时间戳头并命名(unix 秒;推荐用 DefaultTimestampHeader)。时间戳防重放窗的判定在收端(TimestampHMAC 家族或服务端自校验),发出侧职责是把时间戳按约定打出。name 为空串 panic。
type HMACValidator ¶
type HMACValidator struct {
// contains filtered or unexported fields
}
HMACValidator 泛型 HMAC 验签器:签名值 = enc(hmac(algo, key=secret, message=请求体)),按序在 header 链上取第一个在场的值。
func NewForgejoValidator ¶
func NewForgejoValidator(secret []byte) *HMACValidator
NewForgejoValidator Forgejo 形态:X-Forgejo-Signature,回退老分叉沿用的 X-Gitea-Signature——同签名格式(裸 hex HMAC-SHA256),谁的 header 在场 裁谁。
func NewGitHubValidator ¶
func NewGitHubValidator(secret []byte) *HMACValidator
NewGitHubValidator GitHub 形态:X-Hub-Signature-256,值 sha256=<hex> (前缀大小写不敏感剥离)或裸 hex 双形态,HMAC-SHA256 常量时间比对。
func NewGiteaValidator ¶
func NewGiteaValidator(secret []byte) *HMACValidator
NewGiteaValidator Gitea 形态:X-Gitea-Signature,裸 hex HMAC-SHA256。
func NewHMACValidator ¶
func NewHMACValidator(secret []byte, algo crypto.Hash, header string, opts ...HMACOption) *HMACValidator
NewHMACValidator 构造泛型 HMAC 验签器。
secret 为空是构造期配置错误且**安全错误**:**空密钥使 HMAC 验证对可预测 载荷形同虚设**——panic fail-closed(#270 纪律第 2 条)。algo 支持 crypto.SHA256/crypto.SHA384/crypto.SHA512(sha1/sha224 仅存量平台兼容 用),算法白名单外的值非法 panic;header 为空串非法 panic。
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry per-platform 验签器注册表:按平台名路由到对应 Validator。 请求进来先按平台标识(header / URL 路径段 / 配置路由,由服务端自行 判定)取验证器,再裁决。
func (*Registry) Platforms ¶
Platforms 已注册平台名的有序快照(整体拷贝出口,经 SafeMap.Snapshot 锁内拷贝、锁外交付;调试转储「现在注册了哪些平台」一行完成)。
func (*Registry) Register ¶
Register 注册/替换平台的验证器(后写生效——轮换签名密钥时以同名替换 平滑热更)。platform 空串或 validator 为 nil 是构造期配置错误,panic (fail-fast,仓规总则①)。
type Signer ¶ added in v0.42.0
Signer 发出侧签名器接口:Sign 产出已签 payload 的 header 集。实现必须 并发安全(共享 secret 只读);error 仅在幂等 ID 随机源失败时非 nil ——发出方该失败要显式上抛,不能发出去一个空/重复 ID。
type StaticTokenValidator ¶
type StaticTokenValidator struct {
// contains filtered or unexported fields
}
StaticTokenValidator 静态令牌验签:比对 header 值与配置令牌的**字面 相等**(常量时间)——Gitee/GitCode 密码模式、简单平台的固定令牌形态。 与 HMAC 签名模式的分工由 Fallback 组合子裁决(签名优先)。
func NewStaticTokenValidator ¶
func NewStaticTokenValidator(header string, token []byte) *StaticTokenValidator
NewStaticTokenValidator 构造静态令牌验签器。
token 为空是构造期配置错误且**安全错误**:空令牌等于「带着验签器放行 一切」——panic fail-closed(与 HMAC 空 secret 同口径,仓规总则①)。
type TimestampHMACSigner ¶ added in v0.42.0
type TimestampHMACSigner struct {
// contains filtered or unexported fields
}
TimestampHMACSigner TimestampHMACValidator 的发出侧对偶:签名值 = base64(hmac(algo, key=secret, message)),message 缺省按 Gitee 官方口径 timestamp+"\n"+secret 组装(body 参与签名的平台用 SignerWithMessage 注入自己的组装,与验签侧 WithMessage 一一对应)。
func NewGiteeSigner ¶ added in v0.42.0
func NewGiteeSigner(secret []byte, opts ...TimestampSignerOption) *TimestampHMACSigner
NewGiteeSigner Gitee 形态发出侧:X-Gitee-Timestamp(毫秒)+ X-Gitee-Token (base64(HMAC-SHA256(key=secret, message=timestamp+"\n"+secret)))——与 NewGiteeValidator 的签名模式同款。opts 透传 SignerWithMessage / SignerWithClock / SignerWithURLEncoded(须与收端同配)。
func NewTimestampHMACSigner ¶ added in v0.42.0
func NewTimestampHMACSigner(secret []byte, algo crypto.Hash, tsName, sigName string, opts ...TimestampSignerOption) *TimestampHMACSigner
NewTimestampHMACSigner 构造时间戳防重放 HMAC 签名器——NewTimestampHMAC Validator 的逐参数对偶。构造校验同口径:secret 为空 panic fail-closed、 algo 白名单、tsName/sigName 空串 panic、nil 选项 panic。
func (*TimestampHMACSigner) Sign ¶ added in v0.42.0
func (s *TimestampHMACSigner) Sign(payload []byte) (http.Header, error)
Sign 签出带时间戳的 header 集:时间戳头 = 当前毫秒时间戳(Gitee 官方 13 位口径),签名头 = base64(hmac(algo, key=secret, message))。message 缺省不含 body(与验签侧缺省一致——Gitee 口径密钥+时间戳即信物;body 参与签名的平台走 SignerWithMessage)。error 恒为 nil(本签名器无随机 成分),为与 Signer 接口同形保留。
type TimestampHMACValidator ¶
type TimestampHMACValidator struct {
// contains filtered or unexported fields
}
TimestampHMACValidator 时间戳参与 HMAC 的防重放验签器。
func NewTimestampHMACValidator ¶
func NewTimestampHMACValidator(secret []byte, algo crypto.Hash, tsName, sigName string, opts ...TimestampOption) *TimestampHMACValidator
NewTimestampHMACValidator 构造时间戳防重放 HMAC 验签器。
缺省口径 = Gitee 官方文档(WebHook 密钥验证和验证算法):
message = timestamp + "\n" + secret 签名值 = base64(HMAC-SHA256(key=secret, message)) 容忍窗 = DefaultMaxDrift(1h);timestamp 自动识别秒/毫秒
secret 为空 panic fail-closed(同 HMAC 家族);tsName/sigName 空串 panic。algo 白名单同 NewHMACValidator。
type TimestampOption ¶
type TimestampOption func(*TimestampHMACValidator)
TimestampOption TimestampHMACValidator 的构造选项。
func WithClock ¶
func WithClock(now func() time.Time) TimestampOption
WithClock 时钟注入(假时钟确定性测试;与 cache.RunWithClock 同纪律)。
func WithMaxDrift ¶
func WithMaxDrift(d time.Duration) TimestampOption
WithMaxDrift 时间戳容忍窗(必须 >0,防重放窗不存在即失去本验签器的存在 意义——非法值 panic 而非静默关闭校验)。
func WithMessage ¶
func WithMessage(fn func(timestamp string, body []byte) []byte) TimestampOption
WithMessage 自定义签名 message 组装(缺省 timestamp+"\n"+secret,Gitee 官方口径;body 参与签名的平台在此注入,如 timestamp+body)。
func WithQuerySource ¶
func WithQuerySource() TimestampOption
WithQuerySource 时间戳与签名改从 **URL query 参数**取(Gitee 签名形态 之一:timestamp 与 sign 拼在回调 URL 上)。缺省走 header。
func WithURLEncoded ¶
func WithURLEncoded() TimestampOption
WithURLEncoded 签名值经 URL 编码(Java URLEncoder.encode 形态:base64 的 +/= 被转 %2B/%2F/%3D)——比对前先做 PathUnescape 解一层。
type TimestampSignerOption ¶ added in v0.42.0
type TimestampSignerOption func(*TimestampHMACSigner)
TimestampSignerOption TimestampHMACSigner 的构造选项。
func SignerWithMessage ¶ added in v0.42.0
func SignerWithMessage(fn func(timestamp string, body []byte) []byte) TimestampSignerOption
SignerWithMessage 自定义签名 message 组装(与验签侧 WithMessage 同语义 同签名——两侧必须用同一个组装函数,否则验签端算出的 message 对不上)。
func SignerWithURLEncoded ¶ added in v0.42.0
func SignerWithURLEncoded() TimestampSignerOption
SignerWithURLEncoded 签名值 URL 编码(与验签侧 WithURLEncoded 同语义: Java URLEncoder 形态的接收端先解一层再比对——两侧必须同配)。
func TimestampSignerWithClock ¶ added in v0.42.0
func TimestampSignerWithClock(now func() time.Time) TimestampSignerOption
TimestampSignerWithClock 时钟注入(假时钟确定性测试;与验签侧 WithClock 同纪律。与泛型签名器的 SignerWithClock 是两个选项类型,名字带全量前缀消歧)。
type Validator ¶
Validator 单个 webhook 验签器。
r 是已收到的请求(验签器只读 header 与 URL,不读 body);body 是服务端 已读出的**原始**请求体字节(框架各异,读体不是原语的职责)。实现必须 并发安全,且全部比对走常量时间(crypto/hmac.Equal)。
func Fallback ¶
Fallback 按序尝试多个验证器的回退组合子——多平台 header 回退与多模 (签名/密码)消歧的单一实现。
裁决语义(多模消歧的优先序,#270 现场纪律第 5 条):
- 候选返回 ErrMissingSignature(它的验签 header 缺席)→ **落下一个 候选**——「该模式不在场」不是失败,是让位;
- 候选返回**任何其他错误**(ErrBadSignature/ErrStaleTimestamp/自定义) → **立即整体失败**,不再尝试后续候选——签名 header 在场即裁决, 错签硬失败不降级:把签名 header 换成伪造的静态令牌 header 不能 「降级」洗白,同 secret 交叉认证被优先序挡死;
- 全部候选都 ErrMissingSignature → 返回 ErrMissingSignature。
空候选列表是构造期配置错误,panic(仓规总则①)。候选内的 nil 元素 同样 panic——静默跳过会把「配了个空模式」藏成永远让位。
func NewGitCodeValidator ¶
NewGitCodeValidator GitCode 形态:X-GitCode-Signature,回退老分叉沿用的 X-Gitea-Signature(裸 hex HMAC-SHA256)。**签名与静态令牌双模并存**: 再回退 X-GitCode-Token 静态令牌比对——签名模式优先(Fallback 语义: 签名 header 在场即裁决,错签硬失败),令牌为空即双模退化为纯签名。
func NewGiteeValidator ¶
func NewGiteeValidator(secret []byte, password []byte, opts ...TimestampOption) Validator
NewGiteeValidator Gitee 形态:签名模式(X-Gitee-Timestamp + X-Gitee-Token, base64(HMAC-SHA256(key=secret, message=timestamp+"\n"+secret)),容忍窗 缺省 1h 防重放)优先;**无时间戳时**按密码模式消歧(X-Gitee-Token 为 密码明文,常量时间比对)。
AllowPasswordMode 显式 opt-in:密码为空即纯签名模式;密码非空才组合 密码候选——「默认拒绝密码模式」写死在构造期(密码模式只证明「知道 密码」,不绑定报文完整性,能不用就不用)。