Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
ZLMediaKit
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
张翔宇
ZLMediaKit
Commits
f3e551b3
Commit
f3e551b3
authored
7 years ago
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
支持可配置化的RTSP登录认证
parent
02aba328
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
95 行增加
和
6 行删除
+95
-6
src/Common/config.cpp
+7
-0
src/Common/config.h
+11
-0
src/Rtsp/Rtsp.h
+4
-3
src/Rtsp/RtspSession.cpp
+0
-0
src/Rtsp/RtspSession.h
+16
-0
tests/test_server.cpp
+57
-3
没有找到文件。
src/Common/config.cpp
查看文件 @
f3e551b3
...
...
@@ -52,6 +52,9 @@ const char kBroadcastRtspSrcRegisted[] = "kBroadcastRtspSrcRegisted";
const
char
kBroadcastRtmpSrcRegisted
[]
=
"kBroadcastRtmpSrcRegisted"
;
const
char
kBroadcastRecordMP4
[]
=
"kBroadcastRecordMP4"
;
const
char
kBroadcastHttpRequest
[]
=
"kBroadcastHttpRequest"
;
const
char
kBroadcastOnGetRtspRealm
[]
=
"kBroadcastOnGetRtspRealm"
;
const
char
kBroadcastOnRtspAuth
[]
=
"kBroadcastOnRtspAuth"
;
}
//namespace Broadcast
//代理失败最大重试次数
...
...
@@ -174,9 +177,13 @@ const char kPort[] = RTSP_FIELD"port";
#define RTSP_SERVER_NAME "ZLServer"
const
char
kServerName
[]
=
RTSP_FIELD
"serverName"
;
const
char
kAuthBasic
[]
=
RTSP_FIELD
"authBasic"
;
onceToken
token
([](){
mINI
::
Instance
()[
kPort
]
=
RTSP_PORT
;
mINI
::
Instance
()[
kServerName
]
=
RTSP_SERVER_NAME
;
//默认Md5方式认证
mINI
::
Instance
()[
kAuthBasic
]
=
0
;
},
nullptr
);
}
//namespace Rtsp
...
...
This diff is collapsed.
Click to expand it.
src/Common/config.h
查看文件 @
f3e551b3
...
...
@@ -72,6 +72,15 @@ extern const char kBroadcastRecordMP4[];
extern
const
char
kBroadcastHttpRequest
[];
#define BroadcastHttpRequestArgs const Parser &parser,HttpSession::HttpResponseInvoker &invoker,bool &consumed
//该流是否需要认证?是的话调用invoker并传入realm,否则传入空的realm.如果该事件不监听则不认证
extern
const
char
kBroadcastOnGetRtspRealm
[];
#define BroadcastOnGetRtspRealmArgs const char *app,const char *stream,const RtspSession::onGetRealm &invoker
//请求认证用户密码事件,user_name为用户名,must_no_encrypt如果为true,则必须提供明文密码(因为此时是base64认证方式),否则会导致认证失败
//获取到密码后请调用invoker并输入对应类型的密码和密码类型,invoker执行时会匹配密码
extern
const
char
kBroadcastOnRtspAuth
[];
#define BroadcastOnRtspAuthArgs const char *user_name,bool must_no_encrypt,const RtspSession::onAuth &invoker
}
//namespace Broadcast
//代理失败最大重试次数
...
...
@@ -118,6 +127,8 @@ namespace Rtsp {
extern
const
char
kServerName
[];
extern
const
char
kPort
[];
//是否优先base64方式认证?默认Md5方式认证
extern
const
char
kAuthBasic
[];
}
//namespace Rtsp
////////////RTMP服务器配置///////////
...
...
This diff is collapsed.
Click to expand it.
src/Rtsp/Rtsp.h
查看文件 @
f3e551b3
...
...
@@ -186,20 +186,21 @@ public:
return
ret
;
}
static
StrCaseMap
parseArgs
(
const
string
&
str
){
static
StrCaseMap
parseArgs
(
const
string
&
str
,
const
char
*
pair_delim
=
"&"
,
const
char
*
key_delim
=
"="
){
StrCaseMap
ret
;
auto
arg_vec
=
split
(
str
,
"&"
);
auto
arg_vec
=
split
(
str
,
pair_delim
);
for
(
string
&
key_val
:
arg_vec
)
{
if
(
!
key_val
.
size
())
{
continue
;
}
auto
key_val_vec
=
split
(
key_val
,
"="
);
auto
key_val_vec
=
split
(
key_val
,
key_delim
);
if
(
key_val_vec
.
size
()
>=
2
)
{
ret
[
key_val_vec
[
0
]]
=
key_val_vec
[
1
];
}
}
return
ret
;
}
private
:
string
m_strMethod
;
string
m_strUrl
;
...
...
This diff is collapsed.
Click to expand it.
src/Rtsp/RtspSession.cpp
查看文件 @
f3e551b3
差异被折叠。
点击展开。
src/Rtsp/RtspSession.h
查看文件 @
f3e551b3
...
...
@@ -52,6 +52,11 @@ class RtspSession;
class
RtspSession
:
public
TcpLimitedSession
<
MAX_TCP_SESSION
>
{
public
:
typedef
std
::
shared_ptr
<
RtspSession
>
Ptr
;
typedef
std
::
function
<
void
(
const
string
&
realm
)
>
onGetRealm
;
//encrypted为true是则表明是md5加密的密码,否则是明文密码
//在请求明文密码时如果提供md5密码者则会导致认证失败
typedef
std
::
function
<
void
(
bool
encrypted
,
const
string
&
pwd_or_md5
)
>
onAuth
;
RtspSession
(
const
std
::
shared_ptr
<
ThreadPool
>
&
pTh
,
const
Socket
::
Ptr
&
pSock
);
virtual
~
RtspSession
();
void
onRecv
(
const
Socket
::
Buffer
::
Ptr
&
pBuf
)
override
;
...
...
@@ -83,6 +88,7 @@ private:
void
inline
send_UnsupportedTransport
();
//不支持的传输模式
void
inline
send_SessionNotFound
();
//会话id错误
void
inline
send_NotAcceptable
();
//rtsp同时播放数限制
void
splitRtspUrl
(
const
string
&
url
,
string
&
app
,
string
&
stream
);
inline
bool
findStream
();
//根据rtsp url查找 MediaSource实例
inline
void
initSender
(
const
std
::
shared_ptr
<
RtspSession
>
&
pSession
);
//处理rtsp over http,quicktime使用的
...
...
@@ -107,6 +113,13 @@ private:
inline
void
onRcvPeerUdpData
(
int
iTrackIdx
,
const
Socket
::
Buffer
::
Ptr
&
pBuf
,
const
struct
sockaddr
&
addr
);
inline
void
startListenPeerUdpData
();
//认证相关
static
void
onAuthSuccess
(
const
weak_ptr
<
RtspSession
>
&
weakSelf
);
static
void
onAuthFailed
(
const
weak_ptr
<
RtspSession
>
&
weakSelf
,
const
string
&
realm
);
static
void
onAuthUser
(
const
weak_ptr
<
RtspSession
>
&
weakSelf
,
const
string
&
realm
,
const
string
&
authorization
);
static
void
onAuthBasic
(
const
weak_ptr
<
RtspSession
>
&
weakSelf
,
const
string
&
realm
,
const
string
&
strBase64
);
static
void
onAuthDigest
(
const
weak_ptr
<
RtspSession
>
&
weakSelf
,
const
string
&
realm
,
const
string
&
strMd5
);
char
*
m_pcBuf
=
nullptr
;
Ticker
m_ticker
;
Parser
m_parser
;
//rtsp解析类
...
...
@@ -143,6 +156,9 @@ private:
bool
m_bListenPeerUdpData
=
false
;
RtpBroadCaster
::
Ptr
m_pBrdcaster
;
//登录认证
string
m_strNonce
;
//RTSP over HTTP
function
<
void
(
void
)
>
m_onDestory
;
bool
m_bBase64need
=
false
;
//是否需要base64解码
...
...
This diff is collapsed.
Click to expand it.
tests/test_server.cpp
查看文件 @
f3e551b3
...
...
@@ -33,6 +33,7 @@
#include "Rtmp/RtmpSession.h"
#include "Http/HttpSession.h"
#include "Shell/ShellSession.h"
#include "Util/MD5.h"
#ifdef ENABLE_OPENSSL
#include "Util/SSLBox.h"
...
...
@@ -57,6 +58,57 @@ using namespace ZL::Shell;
using
namespace
ZL
::
Thread
;
using
namespace
ZL
::
Network
;
#define REALM "realm_zlmedaikit"
static
onceToken
s_token
([](){
NoticeCenter
::
Instance
().
addListener
(
nullptr
,
Config
::
Broadcast
::
kBroadcastOnGetRtspRealm
,[](
BroadcastOnGetRtspRealmArgs
){
if
(
string
(
"1"
)
==
stream
){
// live/1需要认证
EventPoller
::
Instance
().
async
([
invoker
](){
//该流需要认证,并且设置realm
invoker
(
REALM
);
});
}
else
{
//我们异步执行invoker。
//有时我们要查询redis或数据库来判断该流是否需要认证,通过invoker的方式可以做到完全异步
EventPoller
::
Instance
().
async
([
invoker
](){
//该流我们不需要认证
invoker
(
""
);
});
}
});
NoticeCenter
::
Instance
().
addListener
(
nullptr
,
Config
::
Broadcast
::
kBroadcastOnRtspAuth
,[](
BroadcastOnRtspAuthArgs
){
InfoL
<<
"用户:"
<<
user_name
<<
(
must_no_encrypt
?
" Base64"
:
" MD5"
)
<<
" 方式登录"
;
string
user
=
user_name
;
//假设我们异步读取数据库
EventPoller
::
Instance
().
async
([
must_no_encrypt
,
invoker
,
user
](){
if
(
user
==
"test0"
){
//假设数据库保存的是明文
invoker
(
false
,
"pwd0"
);
return
;
}
if
(
user
==
"test1"
){
//假设数据库保存的是密文
auto
encrypted_pwd
=
MD5
(
user
+
":"
+
REALM
+
":"
+
"pwd1"
).
hexdigest
();
invoker
(
true
,
encrypted_pwd
);
return
;
}
if
(
user
==
"test2"
&&
must_no_encrypt
){
//假设登录的是test2,并且以base64方式登录,此时我们提供加密密码,那么会导致认证失败
//可以通过这个方式屏蔽base64这种不安全的加密方式
invoker
(
true
,
"pwd2"
);
return
;
}
//其他用户密码跟用户名一致
invoker
(
false
,
user
);
});
});
},
nullptr
);
int
main
(
int
argc
,
char
*
argv
[]){
//设置退出信号处理函数
signal
(
SIGINT
,
[](
int
){
EventPoller
::
Instance
().
shutdown
();});
...
...
@@ -68,8 +120,9 @@ int main(int argc,char *argv[]){
//这里是拉流地址,支持rtmp/rtsp协议,负载必须是H264+AAC
//如果是其他不识别的音视频将会被忽略(譬如说h264+adpcm转发后会去除音频)
auto
urlList
=
{
"rtmp://live.hkstv.hk.lxdns.com/live/hks"
,
"rtmp://live.hkstv.hk.lxdns.com/live/hks"
//rtsp链接支持输入用户名密码
"rtsp://admin:jzan123456@192.168.0.122/"
};
/*"rtsp://admin:jzan123456@192.168.0.122/"*/
};
map
<
string
,
PlayerProxy
::
Ptr
>
proxyMap
;
int
i
=
0
;
for
(
auto
&
url
:
urlList
){
...
...
@@ -82,13 +135,14 @@ int main(int argc,char *argv[]){
//http://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
//rtsp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
//rtmp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
PlayerProxy
::
Ptr
player
(
new
PlayerProxy
(
"live"
,
to_string
(
i
++
).
data
()));
PlayerProxy
::
Ptr
player
(
new
PlayerProxy
(
"live"
,
to_string
(
i
).
data
()));
//指定RTP over TCP(播放rtsp时有效)
(
*
player
)[
RtspPlayer
::
kRtpType
]
=
PlayerBase
::
RTP_TCP
;
//开始播放,如果播放失败或者播放中止,将会自动重试若干次,重试次数在配置文件中配置,默认一直重试
player
->
play
(
url
);
//需要保存PlayerProxy,否则作用域结束就会销毁该对象
proxyMap
.
emplace
(
url
,
player
);
proxyMap
.
emplace
(
to_string
(
i
),
player
);
++
i
;
}
#ifdef ENABLE_OPENSSL
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论