简介
本机鉴权是指在本服务器,使用客户端传递过来的参数,来判断是否是合法的推流或者播放请求,例如:推流时使用推流地址为:
rtmp://test.publish.com/app/test?sign=120705DE7E61C5B&expire=1746451971
其中sign根据域名,流名称,过期时间,秘钥拼接后经过md5生成 后台根据域名,流名称,过期时间,秘钥一样拼接计算md5值,与传递过来的sign一致,则校验通过否则不通过;
配置
为了方便配置,mms中设计了一个非常简洁,且扩展性很好,使用起来也很直观的鉴权配置(鉴权配置适用于推流也适用于播放或者回源url生成)
最简化鉴权配置
例如在推流域名test.publish.com.yaml中,配置最简单的(当然还可以生成很复杂的,后面会讲)推流鉴权如下:
type: publish
name: test.publish.com
apps:
- name: app # 接入点名称
publish_auth_check: # 推流鉴权
enabled: true # 使能开关
checks: # 校验项
- "${url_params[publishKey]} == 123" # 静态鉴权(static)
该鉴权表示取url的叫publishKey的参数值,和123这个值做对比,一样则通过,否则鉴权失败。
鉴权占位符
上面为了让大家有直观的感受,介绍了下最简单的鉴权规则,可以看到url_params[publishKey]在这里是一个特殊的表示,我们称为占位符,类似printf中的%s。
占位符使用${}括起来,具体需要替换成什么内容,根据{}里面的内容来,下面我来罗列下目前mms-server里面已经实现的占位符及功能:
占位符 | 解释 | 举例 |
---|---|---|
${domain} | 这个占位符将被域名替换 | |
${app} | 这个占位符将被接入点替换 | |
${stream_name} | 这个占位符将被流名称替换 | |
${stream_type} | 这个占位符将被流类型替换,例如rtmp,webrtc,flv | |
${url_params[key]} | 这个占位符将被url中的相应参数替换,参数名称key | 例如请求rtmp://test.com/app/stream?key=abc,则这个占位符会被替换为abc |
${header_params[key]} | 这个占位符将请求的header中的参数,参数名称key | 例如http的请求头部"key: 123",则这个占位符会被替换为123 |
${params[key]} | 这个占位符将被用户自定义计算生成的参数替换,参数名称key | 后续举例 |
参数生成方法
通过上面的鉴权占位符,获取到域名,接入点,流名称和参数,我们还需要对这些参数进行计算,例如将${domain}/${app}/${stream_name}?key=abc&expire=123,做md5计算得到一个sign值。这就需要一些先确定一些计算方法入md5,sha1,base64等, 方法在params配置里面有效,格式为: 方法名称(参数...) 下面是mms-server里面已经定义的一些方法:
名称 | 参数个数 | 解释 |
---|---|---|
string(p1) | 1 | 例如string(1234)将生成字符串1234 |
get_time() | 0 | 例如get_time()将获取到系统当前的unix时间戳 |
md5_upper(p1) | 1 | 例如md5_upper(${app}/${stream_name}/${url_params[key]}),假如传入key=abc,app=app,stream=stream,那么会把app/stream/abc计算出md5:7B5F8F4411943200D7CDCA6B3A45AA15 |
md5_lower(p1) | 1 | 例如md5_lower(${app}/${stream_name}/${url_params[key]}),假如传入key=abc,app=app,stream=stream,那么会把app/stream/abc计算出md5:7b5f8f4411943200d7cdca6b3a45aa15 |
hmac_sha1(p1,p2) | 2 | hmac_sha1(${params[SignStr]},${params[SecretKey]}),将会使用自定义生成的参数SignStr和SecretKey进行hmac_sha1计算 |
base64(p1) | 1 | base64(${params[HMAC]}),将会使用自定义生成的参数HMAC,做base64计算 |
add(p1,p2) | 2 | add(${params[time]},10),会将自定义时间参数+10得到最终值 |
sub(p1,p2) | 2 | sub(${params[time]},10),会将自定义时间参数-10得到最终值 |
bin_to_hex(p1) | 2 | bin_to_hex(${params[HMAC]}),会将自定义参数HMAC的二进制数据转为16进制字符串 |
配置相关前置内容就介绍完了,下面使用具体的示例,来说明这套鉴权配置系统的灵活性:
配置示例1
配置示例如下:
type: publish
name: test.publish.com
apps:
- name: app # 接入点名称
publish_auth_check: # 限时鉴权(expiry)
params:
key: string(sys@test.publish.com)
time: get_time()
token: md5_upper(${params[key]}/${stream_name}/${url_params[expire]})
checks: # 校验项
- "${url_params[token]} == ${params[token]}"
- "${$url_params[expire]} < ${params[time]}"
自定义生成的参数一般使用的格式为:参数名: 参数生成方法
- key: string(sys@test.publish.com) 表示${params[key]}这个占位符的值是sys@test.publish.com
- time: get_time() 表示${params[time]}这个占位符的值是当前系统unix时间戳,例如:1746451971
- token: md5_upper(params[key]/{stream}/{url_params[expire]}) 表示${params[token]}这个占位符的值是使用前面计算的key/流名称/url中的参数expire计算得到大写的md5值
checks:表示需要进行什么校验
- "${url_params[token]} == ${params[token]}" 表示需要校验url参数中叫token的参数,必须和自定义生成的${params[token]}值一样。
- "${url_params[expire]} < ${params[time]}" 表示需要校验url参数中叫expire的参数,必须小于自定义生成的${params[time]}参数,也就是不能过期
配置示例2
配置示例如下:
type: publish
name: test.publish.com
apps:
- name: app # 接入点名称
publish_auth_check: # 限时鉴权sk(expiry_sk)
params:
SignStr: string(/${app}/${stream_name}/?e=${url_params[e]})
SecretKey: string(312ae9gd2BrCfpTdF4U8aIg9Puh62K4eEGY72Ea_)
AccessKey: string(7O7hf7Ld1RrC_fpZdFvU8aCgOPuhw2K4eapYOdII)
HMAC: hmac_sha1(${params[SecretKey]},${params[SignStr]})
HMACStr: bin_to_hex(${params[HMAC]})
Base64: base64(${params[HMACStr]})
Token: string(${params[AccessKey]}:${params[Base64]})
time: get_time()
checks: # 最终校验项
- "${url_params[token]} == ${params[Token]}"
- "${url_params[e]} < ${params[time]}"
推流url为:
rtmp://test.publish.com/app/test?e=1234&token=7O7hf7Ld1RrC_fpZdFvU8aCgOPuhw2K4eapYOdII:QzkyOUM1NjEzNEQ1RTFBQjVFOUE2MENGMjFFM0E1QjhEMTBGQ0IwQQ==
参数生成如下:
- params[SignStr] = /app/test/?e=1234
- params[SecretKey] = 312ae9gd2BrCfpTdF4U8aIg9Puh62K4eEGY72Ea_
- params[AccessKey] = 7O7hf7Ld1RrC_fpZdFvU8aCgOPuhw2K4eapYOdII
- params[HMAC] = hmac_sha1(${params[SecretKey]},${params[SignStr]}) 表示hmac_sha1(/app/test/?e=1234, 7O7hf7Ld1RrC_fpZdFvU8aCgOPuhw2K4eapYOdII)
- params[HMACStr] = bin_to_hex(${params[HMAC]}) 将HMAC转换为16进制字符串C929C56134D5E1AB5E9A60CF21E3A5B8D10FCB0A
- params[Base64] = base64(${params[HMAC]}) 表示base64(C929C56134D5E1AB5E9A60CF21E3A5B8D10FCB0A) = QzkyOUM1NjEzNEQ1RTFBQjVFOUE2MENGMjFFM0E1QjhEMTBGQ0IwQQ==
- params[Token] = string(${params[AccessKey]}😒{params[Base64]}) 表示:7O7hf7Ld1RrC_fpZdFvU8aCgOPuhw2K4eapYOdII:QzkyOUM1NjEzNEQ1RTFBQjVFOUE2MENGMjFFM0E1QjhEMTBGQ0IwQQ==
- params[time] = get_time() 表示:1746451971(取当前时间) 校验方法如下:
- url的参数token必须和params[token]一样,不一样则失败;
- url参数e(过期时间)必须小于1746451971
目前,在代码层面实现的就是一些常用的计算方法,比如md5,sha1,但代码切分比较清晰,自己增加占位符和方法非常容易。
推流鉴权与拉流鉴权
上面的示例,是使用publish_auth_check来表示推流鉴权,拉流鉴权也类似,名称为play_auth_check:
type: play
name: test.play.com
publish_domain: test.publish.com
apps:
- name: app
play_auth_check:
enabled: true # 使能
params:
key: string(sys@test.publish.com)
time: get_time()
token: md5_upper(${params[key]}/${stream_name}/${url_params[expire]}) #sys@test.publish.com/teststreamtitle/1792866744
checks:
- ${url_params[token]} == ${params[token]}
- ${url_params[expire]} > ${params[time]}