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
42fe7e3d
Commit
42fe7e3d
authored
Jun 13, 2019
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
服务器cookie不再强制关联path
parent
23d793c9
显示空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
176 行增加
和
163 行删除
+176
-163
src/Http/HttpCookieManager.cpp
+115
-108
src/Http/HttpCookieManager.h
+48
-42
src/Http/HttpSession.cpp
+11
-11
src/Http/HttpSession.h
+2
-2
没有找到文件。
src/Http/CookieManager.cpp
→
src/Http/
Http
CookieManager.cpp
查看文件 @
42fe7e3d
...
@@ -27,113 +27,138 @@
...
@@ -27,113 +27,138 @@
#include "Util/util.h"
#include "Util/util.h"
#include "Util/MD5.h"
#include "Util/MD5.h"
#include "Common/config.h"
#include "Common/config.h"
#include "CookieManager.h"
#include "
Http
CookieManager.h"
//////////////////////////////CookieData////////////////////////////////////
namespace
mediakit
{
CookieData
::
CookieData
(
const
CookieManager
::
Ptr
&
manager
,
const
string
&
cookie
,
//////////////////////////////HttpServerCookie////////////////////////////////////
HttpServerCookie
::
HttpServerCookie
(
const
std
::
shared_ptr
<
HttpCookieManager
>
&
manager
,
const
string
&
cookie_name
,
const
string
&
uid
,
const
string
&
uid
,
uint64_t
max_elapsed
,
const
string
&
cookie
,
const
string
&
path
){
uint64_t
max_elapsed
){
_uid
=
uid
;
_uid
=
uid
;
_max_elapsed
=
max_elapsed
;
_max_elapsed
=
max_elapsed
;
_cookie_uuid
=
cookie
;
_cookie_uuid
=
cookie
;
_
path
=
path
;
_
cookie_name
=
cookie_name
;
_manager
=
manager
;
_manager
=
manager
;
manager
->
onAddCookie
(
path
,
uid
,
cookie
);
manager
->
onAddCookie
(
_cookie_name
,
_uid
,
_cookie_uuid
);
}
}
CookieData
::~
CookieData
()
{
HttpServerCookie
::~
HttpServerCookie
()
{
auto
strongManager
=
_manager
.
lock
();
auto
strongManager
=
_manager
.
lock
();
if
(
strongManager
){
if
(
strongManager
){
strongManager
->
onDelCookie
(
_
path
,
_uid
,
_cookie_uuid
);
strongManager
->
onDelCookie
(
_
cookie_name
,
_uid
,
_cookie_uuid
);
}
}
}
}
string
CookieData
::
getCookie
(
const
string
&
cookie_name
)
const
{
return
(
StrPrinter
<<
cookie_name
<<
"="
<<
_cookie_uuid
<<
";expires="
<<
cookieExpireTime
()
<<
";path="
<<
_path
);
const
string
&
HttpServerCookie
::
getUid
()
const
{
return
_uid
;
}
}
bool
CookieData
::
isExpired
()
{
string
HttpServerCookie
::
getCookie
(
const
string
&
path
)
const
{
return
_ticker
.
elapsedTime
()
>
_max_elapsed
*
1000
;
return
(
StrPrinter
<<
_cookie_name
<<
"="
<<
_cookie_uuid
<<
";expires="
<<
cookieExpireTime
()
<<
";path="
<<
path
);
}
const
string
&
HttpServerCookie
::
getCookie
()
const
{
return
_cookie_uuid
;
}
}
void
CookieData
::
updateTime
()
{
const
string
&
HttpServerCookie
::
getCookieName
()
const
{
return
_cookie_name
;
}
void
HttpServerCookie
::
updateTime
()
{
_ticker
.
resetTime
();
_ticker
.
resetTime
();
}
}
const
string
&
CookieData
::
getUid
()
const
{
return
_uid
;
bool
HttpServerCookie
::
isExpired
()
{
return
_ticker
.
elapsedTime
()
>
_max_elapsed
*
1000
;
}
}
string
CookieData
::
cookieExpireTime
()
const
{
string
HttpServerCookie
::
cookieExpireTime
()
const
{
char
buf
[
64
];
char
buf
[
64
];
time_t
tt
=
time
(
NULL
)
+
_max_elapsed
;
time_t
tt
=
time
(
NULL
)
+
_max_elapsed
;
strftime
(
buf
,
sizeof
buf
,
"%a, %b %d %Y %H:%M:%S GMT"
,
gmtime
(
&
tt
));
strftime
(
buf
,
sizeof
buf
,
"%a, %b %d %Y %H:%M:%S GMT"
,
gmtime
(
&
tt
));
return
buf
;
return
buf
;
}
}
//////////////////////////////CookieManager////////////////////////////////////
INSTANCE_IMP
(
HttpCookieManager
);
const
string
&
CookieData
::
getCookie
()
const
{
HttpCookieManager
::
HttpCookieManager
()
{
return
_cookie_uuid
;
//定时删除过期的cookie,防止内存膨胀
_timer
=
std
::
make_shared
<
Timer
>
(
10
,[
this
](){
onManager
();
return
true
;
},
nullptr
);
}
}
const
string
&
CookieData
::
getPath
()
const
{
HttpCookieManager
::~
HttpCookieManager
()
{
return
_path
;
_timer
.
reset
()
;
}
}
//////////////////////////////CookieManager////////////////////////////////////
void
HttpCookieManager
::
onManager
()
{
INSTANCE_IMP
(
CookieManager
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
//先遍历所有类型
for
(
auto
it_name
=
_map_cookie
.
begin
()
;
it_name
!=
_map_cookie
.
end
()
;){
//再遍历该类型下的所有cookie
for
(
auto
it_cookie
=
it_name
->
second
.
begin
()
;
it_cookie
!=
it_name
->
second
.
end
()
;
){
if
(
it_cookie
->
second
->
isExpired
()){
//cookie过期,移除记录
WarnL
<<
it_cookie
->
second
->
getUid
()
<<
" cookie过期"
;
it_cookie
=
it_name
->
second
.
erase
(
it_cookie
);
continue
;
}
++
it_cookie
;
}
if
(
it_name
->
second
.
empty
()){
//该类型下没有任何cooki记录,移除之
WarnL
<<
"该path下没有任何cooki记录:"
<<
it_name
->
first
;
it_name
=
_map_cookie
.
erase
(
it_name
);
continue
;
}
++
it_name
;
}
}
CookieData
::
Ptr
CookieManager
::
addCookie
(
const
string
&
uidIn
,
int
max_client
,
uint64_t
max_elapsed
,
const
string
&
path
)
{
HttpServerCookie
::
Ptr
HttpCookieManager
::
addCookie
(
const
string
&
cookie_name
,
const
string
&
uidIn
,
uint64_t
max_elapsed
,
int
max_client
)
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
auto
cookie
=
_geneator
.
obtain
();
auto
cookie
=
_geneator
.
obtain
();
auto
uid
=
uidIn
.
empty
()
?
cookie
:
uidIn
;
auto
uid
=
uidIn
.
empty
()
?
cookie
:
uidIn
;
auto
oldCookie
=
getOldestCookie
(
uid
,
max_client
,
path
);
auto
oldCookie
=
getOldestCookie
(
cookie_name
,
uid
,
max_client
);
if
(
!
oldCookie
.
empty
()){
if
(
!
oldCookie
.
empty
()){
//假如该账号已经登录了,那么删除老的cookie。
//假如该账号已经登录了,那么删除老的cookie。
//目的是实现单账号多地登录时挤占登录
//目的是实现单账号多地登录时挤占登录
delCookie
(
oldCookie
,
path
);
delCookie
(
cookie_name
,
oldCookie
);
}
}
CookieData
::
Ptr
data
(
new
CookieData
(
shared_from_this
(),
cookie
,
uid
,
max_elapsed
,
path
));
HttpServerCookie
::
Ptr
data
(
new
HttpServerCookie
(
shared_from_this
(),
cookie_name
,
uid
,
cookie
,
max_elapsed
));
//保存该账号下的新cookie
//保存该账号下的新cookie
_map_cookie
[
path
][
cookie
]
=
data
;
_map_cookie
[
cookie_name
][
cookie
]
=
data
;
return
data
;
return
data
;
}
}
bool
CookieManager
::
delCookie
(
const
CookieData
::
Ptr
&
cookie
)
{
HttpServerCookie
::
Ptr
HttpCookieManager
::
getCookie
(
const
string
&
cookie_name
,
const
string
&
cookie
)
{
if
(
!
cookie
){
return
false
;
}
return
delCookie
(
cookie
->
getPath
(),
cookie
->
getCookie
());
}
bool
CookieManager
::
delCookie
(
const
string
&
path
,
const
string
&
cookie
)
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
auto
it
=
_map_cookie
.
find
(
path
);
if
(
it
==
_map_cookie
.
end
()){
return
false
;
}
return
it
->
second
.
erase
(
cookie
);
}
CookieData
::
Ptr
CookieManager
::
getCookie
(
const
string
&
cookie
,
const
string
&
path
)
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
auto
it_
path
=
_map_cookie
.
find
(
path
);
auto
it_
name
=
_map_cookie
.
find
(
cookie_name
);
if
(
it_
path
==
_map_cookie
.
end
()){
if
(
it_
name
==
_map_cookie
.
end
()){
//
该path下没有任何
cookie
//
不存在该类型的
cookie
return
nullptr
;
return
nullptr
;
}
}
auto
it_cookie
=
it_
path
->
second
.
find
(
cookie
);
auto
it_cookie
=
it_
name
->
second
.
find
(
cookie
);
if
(
it_cookie
==
it_
path
->
second
.
end
()){
if
(
it_cookie
==
it_
name
->
second
.
end
()){
//该
path
下没有对应的cookie
//该
类型
下没有对应的cookie
return
nullptr
;
return
nullptr
;
}
}
if
(
it_cookie
->
second
->
isExpired
()){
if
(
it_cookie
->
second
->
isExpired
()){
//cookie过期
//cookie过期
it_
path
->
second
.
erase
(
it_cookie
);
it_
name
->
second
.
erase
(
it_cookie
);
return
nullptr
;
return
nullptr
;
}
}
return
it_cookie
->
second
;
return
it_cookie
->
second
;
}
}
CookieData
::
Ptr
CookieManager
::
getCookie
(
const
StrCaseMap
&
http_header
,
const
string
&
cookie_name
,
const
string
&
path
)
{
HttpServerCookie
::
Ptr
HttpCookieManager
::
getCookie
(
const
string
&
cookie_name
,
const
StrCaseMap
&
http_header
)
{
auto
it
=
http_header
.
find
(
"Cookie"
);
auto
it
=
http_header
.
find
(
"Cookie"
);
if
(
it
==
http_header
.
end
())
{
if
(
it
==
http_header
.
end
())
{
return
nullptr
;
return
nullptr
;
...
@@ -145,64 +170,43 @@ CookieData::Ptr CookieManager::getCookie(const StrCaseMap &http_header, const st
...
@@ -145,64 +170,43 @@ CookieData::Ptr CookieManager::getCookie(const StrCaseMap &http_header, const st
if
(
cookie
.
empty
()){
if
(
cookie
.
empty
()){
return
nullptr
;
return
nullptr
;
}
}
return
CookieManager
::
Instance
().
getCookie
(
cookie
,
path
);
return
HttpCookieManager
::
Instance
().
getCookie
(
cookie_name
,
cookie
);
}
}
CookieManager
::
CookieManager
()
{
bool
HttpCookieManager
::
delCookie
(
const
HttpServerCookie
::
Ptr
&
cookie
)
{
//定时删除过期的cookie,防止内存膨胀
if
(
!
cookie
){
_timer
=
std
::
make_shared
<
Timer
>
(
10
,[
this
](){
return
false
;
onManager
();
}
return
true
;
return
delCookie
(
cookie
->
getCookieName
(),
cookie
->
getCookie
());
},
nullptr
);
}
CookieManager
::~
CookieManager
()
{
_timer
.
reset
();
}
}
void
CookieManager
::
onManager
(
)
{
bool
HttpCookieManager
::
delCookie
(
const
string
&
cookie_name
,
const
string
&
cookie
)
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
//先遍历所有path
auto
it_name
=
_map_cookie
.
find
(
cookie_name
);
for
(
auto
it_path
=
_map_cookie
.
begin
()
;
it_path
!=
_map_cookie
.
end
()
;){
if
(
it_name
==
_map_cookie
.
end
()){
//再遍历该path下的所有cookie
return
false
;
for
(
auto
it_cookie
=
it_path
->
second
.
begin
()
;
it_cookie
!=
it_path
->
second
.
end
()
;
){
if
(
it_cookie
->
second
->
isExpired
()){
//cookie过期,移除记录
WarnL
<<
it_cookie
->
second
->
getUid
()
<<
" cookie过期"
;
it_cookie
=
it_path
->
second
.
erase
(
it_cookie
);
continue
;
}
++
it_cookie
;
}
if
(
it_path
->
second
.
empty
()){
//该path下没有任何cooki记录,移除之
WarnL
<<
"该path下没有任何cooki记录:"
<<
it_path
->
first
;
it_path
=
_map_cookie
.
erase
(
it_path
);
continue
;
}
++
it_path
;
}
}
return
it_name
->
second
.
erase
(
cookie
);
}
}
void
CookieManager
::
onAddCookie
(
const
string
&
path
,
const
string
&
uid
,
const
string
&
cookie
){
void
HttpCookieManager
::
onAddCookie
(
const
string
&
cookie_name
,
const
string
&
uid
,
const
string
&
cookie
){
//添加新的cookie,我们记录下这个uid下有哪些cookie,目的是实现单账号多地登录时挤占登录
//添加新的cookie,我们记录下这个uid下有哪些cookie,目的是实现单账号多地登录时挤占登录
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
//相同用户下可以存在多个cookie(意味多地登录),这些cookie根据登录时间的早晚依次排序
//相同用户下可以存在多个cookie(意味多地登录),这些cookie根据登录时间的早晚依次排序
_map_uid_to_cookie
[
path
][
uid
][
getCurrentMillisecond
()]
=
cookie
;
_map_uid_to_cookie
[
cookie_name
][
uid
][
getCurrentMillisecond
()]
=
cookie
;
}
}
void
CookieManager
::
onDelCookie
(
const
string
&
path
,
const
string
&
uid
,
const
string
&
cookie
){
void
HttpCookieManager
::
onDelCookie
(
const
string
&
cookie_name
,
const
string
&
uid
,
const
string
&
cookie
){
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
//回收随机字符串
//回收随机字符串
_geneator
.
release
(
cookie
);
_geneator
.
release
(
cookie
);
auto
it_
path
=
_map_uid_to_cookie
.
find
(
path
);
auto
it_
name
=
_map_uid_to_cookie
.
find
(
cookie_name
);
if
(
it_
path
==
_map_uid_to_cookie
.
end
()){
if
(
it_
name
==
_map_uid_to_cookie
.
end
()){
//该
path
下未有任意用户登录
//该
类型
下未有任意用户登录
return
;
return
;
}
}
auto
it_uid
=
it_
path
->
second
.
find
(
uid
);
auto
it_uid
=
it_
name
->
second
.
find
(
uid
);
if
(
it_uid
==
it_
path
->
second
.
end
()){
if
(
it_uid
==
it_
name
->
second
.
end
()){
//该用户尚未登录
//该用户尚未登录
return
;
return
;
}
}
...
@@ -221,27 +225,27 @@ void CookieManager::onDelCookie(const string &path,const string &uid,const strin
...
@@ -221,27 +225,27 @@ void CookieManager::onDelCookie(const string &path,const string &uid,const strin
}
}
//该用户名下没有任何设备在线,移除之
//该用户名下没有任何设备在线,移除之
it_
path
->
second
.
erase
(
it_uid
);
it_
name
->
second
.
erase
(
it_uid
);
if
(
it_
path
->
second
.
size
()
!=
0
)
{
if
(
it_
name
->
second
.
size
()
!=
0
)
{
break
;
break
;
}
}
//该
path
下未有任何用户在线,移除之
//该
类型
下未有任何用户在线,移除之
_map_uid_to_cookie
.
erase
(
it_
path
);
_map_uid_to_cookie
.
erase
(
it_
name
);
break
;
break
;
}
}
}
}
string
CookieManager
::
getOldestCookie
(
const
string
&
uid
,
int
max_client
,
const
string
&
path
){
string
HttpCookieManager
::
getOldestCookie
(
const
string
&
cookie_name
,
const
string
&
uid
,
int
max_client
){
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx_cookie
);
auto
it_
path
=
_map_uid_to_cookie
.
find
(
path
);
auto
it_
name
=
_map_uid_to_cookie
.
find
(
cookie_name
);
if
(
it_
path
==
_map_uid_to_cookie
.
end
()){
if
(
it_
name
==
_map_uid_to_cookie
.
end
()){
//
该路径下未有任意
cookie
//
不存在该类型的
cookie
return
""
;
return
""
;
}
}
auto
it_uid
=
it_
path
->
second
.
find
(
uid
);
auto
it_uid
=
it_
name
->
second
.
find
(
uid
);
if
(
it_uid
==
it_
path
->
second
.
end
()){
if
(
it_uid
==
it_
name
->
second
.
end
()){
//该用户从未登录过
//该用户从未登录过
return
""
;
return
""
;
}
}
...
@@ -253,8 +257,8 @@ string CookieManager::getOldestCookie(const string &uid, int max_client,const st
...
@@ -253,8 +257,8 @@ string CookieManager::getOldestCookie(const string &uid, int max_client,const st
return
it_uid
->
second
.
begin
()
->
second
;
return
it_uid
->
second
.
begin
()
->
second
;
}
}
/////////////////////////////////
Cookie
Geneator////////////////////////////////////
/////////////////////////////////
RandStr
Geneator////////////////////////////////////
string
Cookie
Geneator
::
obtain
(){
string
RandStr
Geneator
::
obtain
(){
//获取唯一的防膨胀的随机字符串
//获取唯一的防膨胀的随机字符串
while
(
true
){
while
(
true
){
auto
str
=
obtain_l
();
auto
str
=
obtain_l
();
...
@@ -265,15 +269,17 @@ string CookieGeneator::obtain(){
...
@@ -265,15 +269,17 @@ string CookieGeneator::obtain(){
}
}
}
}
}
}
void
Cookie
Geneator
::
release
(
const
string
&
str
){
void
RandStr
Geneator
::
release
(
const
string
&
str
){
//从防膨胀库中移除
//从防膨胀库中移除
_obtained
.
erase
(
str
);
_obtained
.
erase
(
str
);
}
}
string
Cookie
Geneator
::
obtain_l
(){
string
RandStr
Geneator
::
obtain_l
(){
//12个伪随机字节 + 4个递增的整形字节,然后md5即为随机字符串
//12个伪随机字节 + 4个递增的整形字节,然后md5即为随机字符串
auto
str
=
makeRandStr
(
12
,
false
);
auto
str
=
makeRandStr
(
12
,
false
);
str
.
append
((
char
*
)
&
_index
,
sizeof
(
_index
));
str
.
append
((
char
*
)
&
_index
,
sizeof
(
_index
));
++
_index
;
++
_index
;
return
MD5
(
str
).
hexdigest
();
return
MD5
(
str
).
hexdigest
();
}
}
}
//
namespace
mediakit
\ No newline at end of file
src/Http/CookieManager.h
→
src/Http/
Http
CookieManager.h
查看文件 @
42fe7e3d
...
@@ -40,25 +40,31 @@ using namespace mediakit;
...
@@ -40,25 +40,31 @@ using namespace mediakit;
#define COOKIE_DEFAULT_LIFE (7 * 24 * 60 * 60)
#define COOKIE_DEFAULT_LIFE (7 * 24 * 60 * 60)
class
CookieManager
;
namespace
mediakit
{
class
HttpCookieManager
;
/**
/**
* cookie对象,用于保存cookie的一些相关属性
* cookie对象,用于保存cookie的一些相关属性
*/
*/
class
CookieData
:
public
mINI
,
public
noncopyable
{
class
HttpServerCookie
:
public
mINI
,
public
noncopyable
{
public
:
public
:
typedef
std
::
shared_ptr
<
CookieData
>
Ptr
;
typedef
std
::
shared_ptr
<
HttpServerCookie
>
Ptr
;
/**
/**
* 构建cookie
* 构建cookie
* @param manager cookie管理者对象
* @param manager cookie管理者对象
* @param cookie
cookie随机字符串
* @param cookie
_name cookie名,例如MY_SESSION
* @param uid 用户唯一id
* @param uid 用户唯一id
* @param cookie cookie随机字符串
* @param max_elapsed 最大过期时间,单位秒
* @param max_elapsed 最大过期时间,单位秒
* @param path http路径,譬如/index/files/
*/
*/
CookieData
(
const
std
::
shared_ptr
<
CookieManager
>
&
manager
,
const
string
&
cookie
,
const
string
&
uid
,
uint64_t
max_elapsed
,
const
string
&
path
);
HttpServerCookie
(
const
std
::
shared_ptr
<
HttpCookieManager
>
&
manager
,
~
CookieData
()
;
const
string
&
cookie_name
,
const
string
&
uid
,
const
string
&
cookie
,
uint64_t
max_elapsed
);
~
HttpServerCookie
()
;
/**
/**
* 获取uid
* 获取uid
...
@@ -69,9 +75,10 @@ public:
...
@@ -69,9 +75,10 @@ public:
/**
/**
* 获取http中Set-Cookie字段的值
* 获取http中Set-Cookie字段的值
* @param cookie_name 该cookie的名称,譬如 MY_SESSION
* @param cookie_name 该cookie的名称,譬如 MY_SESSION
* @param path http访问路径
* @return 例如 MY_SESSION=XXXXXX;expires=Wed, Jun 12 2019 06:30:48 GMT;path=/index/files/
* @return 例如 MY_SESSION=XXXXXX;expires=Wed, Jun 12 2019 06:30:48 GMT;path=/index/files/
*/
*/
string
getCookie
(
const
string
&
cookie_name
)
const
;
string
getCookie
(
const
string
&
path
)
const
;
/**
/**
* 获取cookie随机字符串
* 获取cookie随机字符串
...
@@ -80,10 +87,10 @@ public:
...
@@ -80,10 +87,10 @@ public:
const
string
&
getCookie
()
const
;
const
string
&
getCookie
()
const
;
/**
/**
* 获取该cookie
对应的path
* 获取该cookie
名
* @return
* @return
*/
*/
const
string
&
get
Path
()
const
;
const
string
&
get
CookieName
()
const
;
/**
/**
* 更新该cookie的过期时间,可以让此cookie不失效
* 更新该cookie的过期时间,可以让此cookie不失效
...
@@ -99,20 +106,20 @@ private:
...
@@ -99,20 +106,20 @@ private:
string
cookieExpireTime
()
const
;
string
cookieExpireTime
()
const
;
private
:
private
:
string
_uid
;
string
_uid
;
string
_
path
;
string
_
cookie_name
;
string
_cookie_uuid
;
string
_cookie_uuid
;
uint64_t
_max_elapsed
;
uint64_t
_max_elapsed
;
Ticker
_ticker
;
Ticker
_ticker
;
std
::
weak_ptr
<
CookieManager
>
_manager
;
std
::
weak_ptr
<
Http
CookieManager
>
_manager
;
};
};
/**
/**
* cookie随机字符串生成器
* cookie随机字符串生成器
*/
*/
class
Cookie
Geneator
{
class
RandStr
Geneator
{
public
:
public
:
Cookie
Geneator
()
=
default
;
RandStr
Geneator
()
=
default
;
~
Cookie
Geneator
()
=
default
;
~
RandStr
Geneator
()
=
default
;
/**
/**
* 获取不碰撞的随机字符串
* 获取不碰撞的随机字符串
...
@@ -138,95 +145,94 @@ private:
...
@@ -138,95 +145,94 @@ private:
* cookie管理器,用于管理cookie的生成以及过期管理,同时实现了同账号异地挤占登录功能
* cookie管理器,用于管理cookie的生成以及过期管理,同时实现了同账号异地挤占登录功能
* 该对象实现了同账号最多登录若干个设备
* 该对象实现了同账号最多登录若干个设备
*/
*/
class
CookieManager
:
public
std
::
enable_shared_from_this
<
CookieManager
>
{
class
HttpCookieManager
:
public
std
::
enable_shared_from_this
<
Http
CookieManager
>
{
public
:
public
:
typedef
std
::
shared_ptr
<
CookieManager
>
Ptr
;
typedef
std
::
shared_ptr
<
Http
CookieManager
>
Ptr
;
friend
class
CookieData
;
friend
class
HttpServerCookie
;
~
CookieManager
();
~
Http
CookieManager
();
/**
/**
* 获取单例
* 获取单例
*/
*/
static
CookieManager
&
Instance
();
static
Http
CookieManager
&
Instance
();
/**
/**
* 添加cookie
* 添加cookie
* @param cookie_name cookie名,例如MY_SESSION
* @param uid 用户id,如果为空则为匿名登录
* @param uid 用户id,如果为空则为匿名登录
* @param max_client 该账号最多登录多少个设备
* @param max_client 该账号最多登录多少个设备
* @param max_elapsed 该cookie过期时间,单位秒
* @param max_elapsed 该cookie过期时间,单位秒
* @param path 该cookie对应的http路径
* @return cookie对象
* @return cookie对象
*/
*/
CookieData
::
Ptr
addCookie
(
const
string
&
uid
,
int
max_client
,
uint64_t
max_elapsed
=
COOKIE_DEFAULT_LIFE
,
const
string
&
path
=
"/"
);
HttpServerCookie
::
Ptr
addCookie
(
const
string
&
cookie_name
,
const
string
&
uid
,
uint64_t
max_elapsed
=
COOKIE_DEFAULT_LIFE
,
int
max_client
=
1
);
/**
/**
* 根据cookie随机字符串查找cookie对象
* 根据cookie随机字符串查找cookie对象
* @param cookie_name cookie名,例如MY_SESSION
* @param cookie cookie随机字符串
* @param cookie cookie随机字符串
* @param path 该cookie对应的http路径
* @return cookie对象,可以为nullptr
* @return cookie对象,可以为nullptr
*/
*/
CookieData
::
Ptr
getCookie
(
const
string
&
cookie
,
const
string
&
path
=
"/"
);
HttpServerCookie
::
Ptr
getCookie
(
const
string
&
cookie_name
,
const
string
&
cookie
);
/**
/**
* 从http头中获取cookie对象
* 从http头中获取cookie对象
* @param cookie_name cookie名,例如MY_SESSION
* @param http_header http头
* @param http_header http头
* @param cookie_name cookie名
* @param path http路径
* @return cookie对象
* @return cookie对象
*/
*/
CookieData
::
Ptr
getCookie
(
const
StrCaseMap
&
http_header
,
const
string
&
cookie_name
,
const
string
&
path
=
"/"
);
HttpServerCookie
::
Ptr
getCookie
(
const
string
&
cookie_name
,
const
StrCaseMap
&
http_header
);
/**
/**
* 删除cookie,用户登出时使用
* 删除cookie,用户登出时使用
* @param cookie cookie对象,可以为nullptr
* @param cookie cookie对象,可以为nullptr
* @return
* @return
*/
*/
bool
delCookie
(
const
CookieData
::
Ptr
&
cookie
);
bool
delCookie
(
const
HttpServerCookie
::
Ptr
&
cookie
);
/**
/**
* 获取某用户名下最先登录时的cookie,目的是实现某用户下最多登录若干个设备
* 获取某用户名下最先登录时的cookie,目的是实现某用户下最多登录若干个设备
* @param
path http路径
* @param
cookie_name cookie名,例如MY_SESSION
* @param uid 用户id
* @param uid 用户id
* @param max_client 最多登录的设备个数
* @param max_client 最多登录的设备个数
* @return 最早的cookie随机字符串
* @return 最早的cookie随机字符串
*/
*/
string
getOldestCookie
(
const
string
&
uid
,
int
max_client
,
const
string
&
path
=
"/"
);
string
getOldestCookie
(
const
string
&
cookie_name
,
const
string
&
uid
,
int
max_client
=
1
);
private
:
private
:
CookieManager
();
Http
CookieManager
();
void
onManager
();
void
onManager
();
/**
/**
* 构造cookie对象时触发,目的是记录某账号下多个cookie
* 构造cookie对象时触发,目的是记录某账号下多个cookie
* @param
path http路径
* @param
cookie_name cookie名,例如MY_SESSION
* @param uid 用户id
* @param uid 用户id
* @param cookie cookie随机字符串
* @param cookie cookie随机字符串
*/
*/
void
onAddCookie
(
const
string
&
path
,
const
string
&
uid
,
const
string
&
cookie
);
void
onAddCookie
(
const
string
&
cookie_name
,
const
string
&
uid
,
const
string
&
cookie
);
/**
/**
* 析构cookie对象时触发
* 析构cookie对象时触发
* @param
path http路径
* @param
cookie_name cookie名,例如MY_SESSION
* @param uid 用户id
* @param uid 用户id
* @param cookie cookie随机字符串
* @param cookie cookie随机字符串
*/
*/
void
onDelCookie
(
const
string
&
path
,
const
string
&
uid
,
const
string
&
cookie
);
void
onDelCookie
(
const
string
&
cookie_name
,
const
string
&
uid
,
const
string
&
cookie
);
/**
/**
* 删除cookie
* 删除cookie
* @param
path http路径
* @param
cookie_name cookie名,例如MY_SESSION
* @param cookie cookie随机字符串
* @param cookie cookie随机字符串
* @return 成功true
* @return 成功true
*/
*/
bool
delCookie
(
const
string
&
path
,
const
string
&
cookie
);
bool
delCookie
(
const
string
&
cookie_name
,
const
string
&
cookie
);
private
:
private
:
unordered_map
<
string
/*
path*/
,
unordered_map
<
string
/*cookie*/
,
CookieData
::
Ptr
/*cookie_data*/
>
>
_map_cookie
;
unordered_map
<
string
/*
cookie_name*/
,
unordered_map
<
string
/*cookie*/
,
HttpServerCookie
::
Ptr
/*cookie_data*/
>
>
_map_cookie
;
unordered_map
<
string
/*
path
*/
,
unordered_map
<
string
/*uid*/
,
map
<
uint64_t
/*cookie time stamp*/
,
string
/*cookie*/
>
>
>
_map_uid_to_cookie
;
unordered_map
<
string
/*
cookie_name
*/
,
unordered_map
<
string
/*uid*/
,
map
<
uint64_t
/*cookie time stamp*/
,
string
/*cookie*/
>
>
>
_map_uid_to_cookie
;
recursive_mutex
_mtx_cookie
;
recursive_mutex
_mtx_cookie
;
Timer
::
Ptr
_timer
;
Timer
::
Ptr
_timer
;
Cookie
Geneator
_geneator
;
RandStr
Geneator
_geneator
;
};
};
}
//namespace mediakit
#endif //SRC_HTTP_COOKIEMANAGER_H
#endif //SRC_HTTP_COOKIEMANAGER_H
src/Http/HttpSession.cpp
查看文件 @
42fe7e3d
...
@@ -51,7 +51,6 @@ namespace mediakit {
...
@@ -51,7 +51,6 @@ namespace mediakit {
static
int
kSockFlags
=
SOCKET_DEFAULE_FLAGS
|
FLAG_MORE
;
static
int
kSockFlags
=
SOCKET_DEFAULE_FLAGS
|
FLAG_MORE
;
static
const
string
kCookieName
=
"ZL_COOKIE"
;
static
const
string
kCookieName
=
"ZL_COOKIE"
;
static
const
string
kAccessPathKey
=
"kAccessPathKey"
;
static
const
string
kAccessPathKey
=
"kAccessPathKey"
;
static
int
kMaxClientPerUid
=
1
;
static
const
string
kAccessDirUnauthorized
=
"你没有权限访问该目录"
;
static
const
string
kAccessDirUnauthorized
=
"你没有权限访问该目录"
;
static
const
string
kAccessFileUnauthorized
=
"你没有权限访问该文件"
;
static
const
string
kAccessFileUnauthorized
=
"你没有权限访问该文件"
;
...
@@ -331,7 +330,7 @@ inline string HttpSession::getClientUid(){
...
@@ -331,7 +330,7 @@ inline string HttpSession::getClientUid(){
NoticeCenter
::
Instance
().
emitEventNoCopy
(
Broadcast
::
kBroadcastTrackHttpClient
,
_parser
,
uid
,
*
this
);
NoticeCenter
::
Instance
().
emitEventNoCopy
(
Broadcast
::
kBroadcastTrackHttpClient
,
_parser
,
uid
,
*
this
);
return
uid
;
return
uid
;
}
}
inline
void
HttpSession
::
canAccessPath
(
const
string
&
path_in
,
bool
is_dir
,
const
function
<
void
(
bool
canAccess
,
const
CookieData
::
Ptr
&
cookie
)
>
&
callback_in
){
inline
void
HttpSession
::
canAccessPath
(
const
string
&
path_in
,
bool
is_dir
,
const
function
<
void
(
bool
canAccess
,
const
HttpServerCookie
::
Ptr
&
cookie
)
>
&
callback_in
){
if
(
NoticeCenter
::
Instance
().
listenerSize
(
Broadcast
::
kBroadcastHttpAccess
)
==
0
){
if
(
NoticeCenter
::
Instance
().
listenerSize
(
Broadcast
::
kBroadcastHttpAccess
)
==
0
){
//该事件无人监听,那么就不做cookie查找这样费时的操作
//该事件无人监听,那么就不做cookie查找这样费时的操作
callback_in
(
true
,
nullptr
);
callback_in
(
true
,
nullptr
);
...
@@ -340,7 +339,7 @@ inline void HttpSession::canAccessPath(const string &path_in,bool is_dir,const f
...
@@ -340,7 +339,7 @@ inline void HttpSession::canAccessPath(const string &path_in,bool is_dir,const f
auto
path
=
path_in
;
auto
path
=
path_in
;
replace
(
const_cast
<
string
&>
(
path
),
"//"
,
"/"
);
replace
(
const_cast
<
string
&>
(
path
),
"//"
,
"/"
);
auto
callback
=
[
callback_in
,
this
](
bool
canAccess
,
const
CookieData
::
Ptr
&
cookie
){
auto
callback
=
[
callback_in
,
this
](
bool
canAccess
,
const
HttpServerCookie
::
Ptr
&
cookie
){
try
{
try
{
callback_in
(
canAccess
,
cookie
);
callback_in
(
canAccess
,
cookie
);
}
catch
(
SockException
&
ex
){
}
catch
(
SockException
&
ex
){
...
@@ -353,7 +352,7 @@ inline void HttpSession::canAccessPath(const string &path_in,bool is_dir,const f
...
@@ -353,7 +352,7 @@ inline void HttpSession::canAccessPath(const string &path_in,bool is_dir,const f
};
};
//根据http头中的cookie字段获取cookie
//根据http头中的cookie字段获取cookie
auto
cookie
=
CookieManager
::
Instance
().
getCookie
(
_parser
.
getValues
(),
kCookieName
);
auto
cookie
=
HttpCookieManager
::
Instance
().
getCookie
(
kCookieName
,
_parser
.
getValues
()
);
if
(
cookie
)
{
if
(
cookie
)
{
//判断该用户是否有权限访问该目录,并且不再设置客户端cookie
//判断该用户是否有权限访问该目录,并且不再设置客户端cookie
callback
(
!
(
*
cookie
)[
kAccessPathKey
].
empty
()
&&
path
.
find
((
*
cookie
)[
kAccessPathKey
])
==
0
,
nullptr
);
callback
(
!
(
*
cookie
)[
kAccessPathKey
].
empty
()
&&
path
.
find
((
*
cookie
)[
kAccessPathKey
])
==
0
,
nullptr
);
...
@@ -362,10 +361,10 @@ inline void HttpSession::canAccessPath(const string &path_in,bool is_dir,const f
...
@@ -362,10 +361,10 @@ inline void HttpSession::canAccessPath(const string &path_in,bool is_dir,const f
//根据该用户的用户名获取cookie
//根据该用户的用户名获取cookie
string
uid
=
getClientUid
();
string
uid
=
getClientUid
();
auto
cookie_str
=
CookieManager
::
Instance
().
getOldestCookie
(
uid
,
kMaxClientPerU
id
);
auto
cookie_str
=
HttpCookieManager
::
Instance
().
getOldestCookie
(
kCookieName
,
u
id
);
if
(
!
cookie_str
.
empty
()){
if
(
!
cookie_str
.
empty
()){
//该用户已经登录过了,但是它(http客户端)貌似不支持cookie,所以我们只能通过它的用户名获取cookie
//该用户已经登录过了,但是它(http客户端)貌似不支持cookie,所以我们只能通过它的用户名获取cookie
cookie
=
CookieManager
::
Instance
().
getCookie
(
cookie_str
);
cookie
=
HttpCookieManager
::
Instance
().
getCookie
(
kCookieName
,
cookie_str
);
if
(
cookie
)
{
if
(
cookie
)
{
//判断该用户是否有权限访问该目录,并且不再设置客户端cookie
//判断该用户是否有权限访问该目录,并且不再设置客户端cookie
callback
(
!
(
*
cookie
)[
kAccessPathKey
].
empty
()
&&
path
.
find
((
*
cookie
)[
kAccessPathKey
])
==
0
,
nullptr
);
callback
(
!
(
*
cookie
)[
kAccessPathKey
].
empty
()
&&
path
.
find
((
*
cookie
)[
kAccessPathKey
])
==
0
,
nullptr
);
...
@@ -390,12 +389,13 @@ inline void HttpSession::canAccessPath(const string &path_in,bool is_dir,const f
...
@@ -390,12 +389,13 @@ inline void HttpSession::canAccessPath(const string &path_in,bool is_dir,const f
}
}
if
(
cookieLifeSecond
){
if
(
cookieLifeSecond
){
//我们给用户生成追踪cookie
//我们给用户生成追踪cookie
auto
cookie
=
CookieManager
::
Instance
().
addCookie
(
uid
,
kMaxClientPerUid
,
cookieLifeSecond
);
auto
cookie
=
HttpCookieManager
::
Instance
().
addCookie
(
kCookieName
,
uid
,
cookieLifeSecond
);
//记录用户能访问的路径
//记录用户能访问的路径
(
*
cookie
)[
kAccessPathKey
]
=
accessPath
;
(
*
cookie
)[
kAccessPathKey
]
=
accessPath
;
//判断该用户是否有权限访问该目录,并且设置客户端cookie
//判断该用户是否有权限访问该目录,并且设置客户端cookie
callback
(
!
accessPath
.
empty
()
&&
path
.
find
(
accessPath
)
==
0
,
cookie
);
callback
(
!
accessPath
.
empty
()
&&
path
.
find
(
accessPath
)
==
0
,
cookie
);
}
else
{
}
else
{
//仅限本次访问文件
callback
(
!
accessPath
.
empty
()
&&
path
.
find
(
accessPath
)
==
0
,
nullptr
);
callback
(
!
accessPath
.
empty
()
&&
path
.
find
(
accessPath
)
==
0
,
nullptr
);
}
}
});
});
...
@@ -462,13 +462,13 @@ inline void HttpSession::Handle_Req_GET(int64_t &content_len) {
...
@@ -462,13 +462,13 @@ inline void HttpSession::Handle_Req_GET(int64_t &content_len) {
}
}
//判断是否有权限访问该目录
//判断是否有权限访问该目录
canAccessPath
(
_parser
.
Url
(),
true
,[
this
,
bClose
,
strFile
,
strMeun
](
bool
canAccess
,
const
CookieData
::
Ptr
&
cookie
){
canAccessPath
(
_parser
.
Url
(),
true
,[
this
,
bClose
,
strFile
,
strMeun
](
bool
canAccess
,
const
HttpServerCookie
::
Ptr
&
cookie
){
if
(
!
canAccess
){
if
(
!
canAccess
){
const_cast
<
string
&>
(
strMeun
)
=
kAccessDirUnauthorized
;
const_cast
<
string
&>
(
strMeun
)
=
kAccessDirUnauthorized
;
}
}
auto
headerOut
=
makeHttpHeader
(
bClose
,
strMeun
.
size
());
auto
headerOut
=
makeHttpHeader
(
bClose
,
strMeun
.
size
());
if
(
cookie
){
if
(
cookie
){
headerOut
[
"Set-Cookie"
]
=
cookie
->
getCookie
(
kCookieName
);
headerOut
[
"Set-Cookie"
]
=
cookie
->
getCookie
(
(
*
cookie
)[
kAccessPathKey
]
);
}
}
sendResponse
(
canAccess
?
"200 OK"
:
"401 Unauthorized"
,
headerOut
,
strMeun
);
sendResponse
(
canAccess
?
"200 OK"
:
"401 Unauthorized"
,
headerOut
,
strMeun
);
throw
SockException
(
bClose
?
Err_shutdown
:
Err_success
,
"close connection after access folder"
);
throw
SockException
(
bClose
?
Err_shutdown
:
Err_success
,
"close connection after access folder"
);
...
@@ -499,7 +499,7 @@ inline void HttpSession::Handle_Req_GET(int64_t &content_len) {
...
@@ -499,7 +499,7 @@ inline void HttpSession::Handle_Req_GET(int64_t &content_len) {
auto
parser
=
_parser
;
auto
parser
=
_parser
;
//判断是否有权限访问该文件
//判断是否有权限访问该文件
canAccessPath
(
_parser
.
Url
(),
false
,[
this
,
parser
,
tFileStat
,
pFilePtr
,
bClose
,
strFile
](
bool
canAccess
,
const
CookieData
::
Ptr
&
cookie
){
canAccessPath
(
_parser
.
Url
(),
false
,[
this
,
parser
,
tFileStat
,
pFilePtr
,
bClose
,
strFile
](
bool
canAccess
,
const
HttpServerCookie
::
Ptr
&
cookie
){
//判断是不是分节下载
//判断是不是分节下载
auto
&
strRange
=
parser
[
"Range"
];
auto
&
strRange
=
parser
[
"Range"
];
int64_t
iRangeStart
=
0
,
iRangeEnd
=
0
;
int64_t
iRangeStart
=
0
,
iRangeEnd
=
0
;
...
@@ -530,7 +530,7 @@ inline void HttpSession::Handle_Req_GET(int64_t &content_len) {
...
@@ -530,7 +530,7 @@ inline void HttpSession::Handle_Req_GET(int64_t &content_len) {
}
}
if
(
cookie
){
if
(
cookie
){
httpHeader
[
"Set-Cookie"
]
=
cookie
->
getCookie
(
kCookieName
);
httpHeader
[
"Set-Cookie"
]
=
cookie
->
getCookie
(
(
*
cookie
)[
kAccessPathKey
]
);
}
}
//先回复HTTP头部分
//先回复HTTP头部分
sendResponse
(
canAccess
?
pcHttpResult
:
"401 Unauthorized"
,
httpHeader
,
canAccess
?
""
:
kAccessFileUnauthorized
);
sendResponse
(
canAccess
?
pcHttpResult
:
"401 Unauthorized"
,
httpHeader
,
canAccess
?
""
:
kAccessFileUnauthorized
);
...
...
src/Http/HttpSession.h
查看文件 @
42fe7e3d
...
@@ -35,7 +35,7 @@
...
@@ -35,7 +35,7 @@
#include "RtmpMuxer/FlvMuxer.h"
#include "RtmpMuxer/FlvMuxer.h"
#include "HttpRequestSplitter.h"
#include "HttpRequestSplitter.h"
#include "WebSocketSplitter.h"
#include "WebSocketSplitter.h"
#include "CookieManager.h"
#include "
Http
CookieManager.h"
using
namespace
std
;
using
namespace
std
;
using
namespace
toolkit
;
using
namespace
toolkit
;
...
@@ -119,7 +119,7 @@ private:
...
@@ -119,7 +119,7 @@ private:
* @param is_dir path是否为目录
* @param is_dir path是否为目录
* @param callback 有权限或无权限的回调
* @param callback 有权限或无权限的回调
*/
*/
inline
void
canAccessPath
(
const
string
&
path
,
bool
is_dir
,
const
function
<
void
(
bool
canAccess
,
const
CookieData
::
Ptr
&
cookie
)
>
&
callback
);
inline
void
canAccessPath
(
const
string
&
path
,
bool
is_dir
,
const
function
<
void
(
bool
canAccess
,
const
HttpServerCookie
::
Ptr
&
cookie
)
>
&
callback
);
//获取用户唯一识别id,我们默认为ip+端口号
//获取用户唯一识别id,我们默认为ip+端口号
inline
string
getClientUid
();
inline
string
getClientUid
();
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论