跳到正文

鉴权与凭据

了解 Kiln 的四类凭据、会话 JWT 签名密钥、管理员 API 令牌,以及生产环境的安全设置。

更新于 Markdown 版本

Kiln 使用四类凭据,各自只负责一类访问:公开端点无需凭据,登录会话用于管理控制台,管理员 API 令牌用于脚本和自动化,路径式播放密钥用于播放器和播放列表分发。不同凭据的权限互不继承,也不能相互转换。

凭据总览

凭据 格式 适用场景 生命周期
公开端点 不带凭据 健康检查、指标、EPG、台标 不适用
登录会话 JWT Authorization: Bearer <jwt>,Ed25519 签名 管理控制台、交互式调试 token_ttl_hours(默认 24 小时),修改登录凭据后立即失效
管理员 API 令牌 kiln_v1_ 前缀 + 48 位随机字符 脚本、CI、外部管理工具 创建时设定有效期,可轮换、可撤销
路径式播放密钥 v1 前缀 + 126 位随机字符,写在 URL 路径里 播放器与播放列表分发 创建时设定有效期,可吊销

用户与角色

用户写在配置文件的 [[auth.users]] 数组里,至少需要一个,否则启动时校验失败。每个用户必须提供 usernamepassword_hashrole,用户名不可重复。

kiln.tomltoml
[[auth.users]]
username = "admin"
password_hash = "$2a$10$..."
role = "admin"

[[auth.users]]
username = "operator"
password_hash = "$2a$10$..."
role = "viewer"
channel_ids = ["demo-hls", "demo-dash"]

role = "admin" 拥有全部权限,也是进入管理控制台的门槛:控制台在登录后会再查一次 /v1/me,角色不是 admin 就会被退回登录页。其它角色受 channel_ids 约束,只能在频道列表、播放列表和运行状态里看到并播放列出的频道;channel_ids 留空表示不限制频道。

口令以 bcrypt 哈希保存,配置里不出现明文。生成哈希:

make hash PASSWORD='your-password'
go run scripts/hash-password.go 'your-password'

会话 JWT

登录端点 POST /v1/auth/login 用用户名和口令换一枚 Ed25519 签名的 JWT,响应里同时给出过期时间、用户名和角色。

curl -s http://127.0.0.1:8080/v1/auth/login \
  -H 'content-type: application/json' \
  -d '{"username":"admin","password":"your-password"}'

签名密钥

签名算法固定为 EdDSA,服务端按下面的顺序解析私钥,先命中者生效:

配置内联 PEM

auth.token_private_key,或环境变量 KILN_TOKEN_PRIVATE_KEY

密钥文件路径

auth.token_private_key_file,或环境变量 KILN_TOKEN_PRIVATE_KEY_FILE

数据目录自动生成

以上都没有时,读取 {data_dir}/auth/ed25519.pem;文件不存在就地生成一对新密钥,私钥权限 0600,公钥写到 {data_dir}/auth/ed25519.pub.pem

公钥是可选的:不填就从私钥推导。如果同时提供了 token_public_keytoken_public_key_file,服务端会校验它与私钥匹配,不匹配直接启动失败。私钥、私钥文件和 server.data_dir 三者必须至少有一个,否则配置校验不通过。

手动生成一对密钥:

go run scripts/gen-jwt-keys.go ./secrets   # 写出 ed25519.pem / ed25519.pub.pem

校验规则与限流

  • 签发的令牌带 issaudexpiatnbfsub 和唯一的随机 jti;校验时四项时间断言全部生效,允许 30 秒时钟偏差。
  • token_issuertoken_audience 默认都是 kiln,校验时必须与签发时一致。改了这两项,历史令牌全部作废。
  • token_ttl_hours 默认 24,取值小于等于 0 时按 24 小时处理。
  • 登录限流按客户端 IP 计数,login_rate_per_min 默认每分钟 20 次,超出返回 429。修改登录凭据的接口另有一条按「用户名 + IP」计数的限流。
  • 管理控制台用于「预览」的临时令牌是一种特殊会话:只绑定单个频道、默认 5 分钟过期,且被管理接口显式拒绝,只能用于播放。

管理员 API 令牌

会话 JWT 供浏览器使用,不适合交给脚本。长期自动化请在管理控制台的「设置 → 管理员 API 令牌」中创建独立凭据。

签发与保管

明文形如 kiln_v1_ 加 48 位随机字符,只在创建(或轮换)后展示一次。服务端只保存它的 SHA-256 摘要,外加一段用于识别的前缀,因此没有任何接口能把明文找回来,丢了就只能轮换。

curl -s http://127.0.0.1:8080/v1/admin/channels \
  -H "authorization: Bearer kiln_v1_..." | jq

四种权限

权限互不隐含,按用途勾选:

read

读取频道、设置、出口配置与各类日志。

write

新增与修改配置,包括导入导出 M3U,但不能删除。

delete

删除频道与出口条目、吊销播放密钥、清空访问日志。

refresh

探测节目源、刷新 EPG、预热与预览频道、停止会话、测试网络出口。

有效期、轮换与撤销

  • 有效期在创建时设定,也可以后续调整,上限 10 年;不设则永不过期。
  • 轮换保留名称、权限和有效期,只换掉随机值,旧值立即失效,新明文同样只显示一次。替换泄露的凭据优先用轮换。
  • 撤销不可恢复,之后所有使用该 Token 的请求都会得到 401。
  • 删除记录会让 Token 立即失效并从列表里消失,但审计日志中已记录的前缀快照仍会保留。
  • 编辑、轮换、撤销、删除都要求携带 If-Match 头传入当前 revision,缺失或过期返回 409,避免两个管理端并发覆盖。

审计日志

每一次使用管理员 API 令牌的请求都会留下记录,无论获准还是被拒。记录包括令牌前缀、方法与路径、所需权限、判定结果与拒绝原因、HTTP 状态、客户端地址、User-Agent 和请求编号。控制台会在同一张卡片下方显示最近的调用记录。

拒绝原因是固定的几种,便于定位:

原因 状态 含义
revoked 401 Token 已撤销或被停用
expired 401 Token 已过期
session_required 403 该路由只认登录会话
route_not_available 403 该路由未登记给 API Token
missing_scope 403 Token 缺少这条路由所需的权限

边界

修改登录凭据

PUT /v1/me/credentials 用于改用户名或口令,只接受管理员登录会话,API Token 调用会被拒绝。请求必须带当前口令,新口令长度为 8 到 72 字节,用户名不超过 64 个字符且不能含控制字符。

保存成功后会做三件事:把新凭据作为覆盖项写入状态库、递增该账户的凭据版本号、返回一枚全新的会话令牌。版本号递增意味着此前签发的所有会话立即作废,其他设备会被登出。在管理控制台里,这个操作在「系统设置 → 账户与语言」或右上角账户菜单里。

[security] 的安全语义

kiln.tomltoml
[security]
play_require_auth = true
allowed_hosts = []
# cors_origins = ["http://127.0.0.1:5173"]
# public_hosts = ["kiln.lan", "origin.example.com", "localhost"]
max_playlist_bytes = 8388608
max_body_bytes = 1048576
作用
play_require_auth 播放端点是否需要凭据,默认开启。关闭后 /v1/play/ 下的地址对任何人可用,仅供本机调试;环境变量 KILN_PLAY_OPEN=1 是同一个开关
allowed_hosts 出站私网豁免列表。解析到回环或私有地址的源站主机名与 IP 必须显式加入,上游与频道声明不会自动豁免
public_hosts 入站白名单,按请求的 Host 头判定。非空时不在列表内的请求一律 403,回环地址上的健康检查除外;留空表示不限制
cors_origins 允许携带凭据跨源访问的来源列表。留空表示只允许同源,浏览器侧不会收到任何 CORS 响应头
max_playlist_bytes 单个上游播放列表的读取上限,默认 8 MiB,防止超大清单拖垮内存
max_body_bytes 管理接口请求体的读取上限,默认 1 MiB;导入类接口按倍数放宽

管理接口的响应还会带上 X-Content-Type-OptionsReferrer-PolicyX-Frame-Options: DENY、严格的 Content-Security-Policy 与禁止存储的缓存策略。EPG、台标和不可变媒体响应使用各自的缓存规则。X-Frame-Options 可防止管理控制台被嵌入第三方页面。

播放密钥

播放密钥是给播放器和播放列表分发用的独立凭据:它出现在 URL 路径里(/p/{token}/...),可以限定频道范围与有效期,可以随时吊销,每次取用都会记入播放访问日志,日志中的路径只保留密钥前缀。它与登录凭据完全隔离,把播放地址交给第三方设备也不会泄露管理权限。

创建、吊销与访问日志都在管理控制台的「访问控制」里,用法见 播放与分发

生产加固清单

换掉示例口令

示例配置里的 admin / admin 只用于第一次启动。用 make hash 生成新的 bcrypt 哈希替换 password_hash,或登录后直接在控制台里改。

固定 JWT 签名密钥

生产环境显式配置 token_private_key_fileKILN_TOKEN_PRIVATE_KEY_FILE,把密钥纳入备份与轮换流程。依赖数据目录自动生成的密钥会随目录一起丢失,届时所有会话失效。

保持 play_require_auth 开启

确认没有在环境里遗留 KILN_PLAY_OPEN=1。对外分发用播放密钥,不要关闭播放鉴权。

收紧主机白名单

public_hosts 限定对外域名。只有确需访问回环或私网源站时,才把对应主机名或 IP 显式加入 allowed_hosts;频道配置不会替代这一步。

给自动化独立 Token

脚本一律使用管理员 API 令牌,按用途授予最小权限并设置有效期,定期轮换,并通过审计日志核对调用来源。

配置项的完整取值范围见 配置参考,环境变量见 环境变量

导航

输入以搜索…

↑↓ 移动↵ 打开Esc 关闭