Commit 42fe7e3d by xiongziliang

服务器cookie不再强制关联path

parent 23d793c9
...@@ -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& getPath() const; const string& getCookieName() 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<HttpCookieManager> _manager;
}; };
/** /**
* cookie随机字符串生成器 * cookie随机字符串生成器
*/ */
class CookieGeneator{ class RandStrGeneator{
public: public:
CookieGeneator() = default; RandStrGeneator() = default;
~CookieGeneator() = default; ~RandStrGeneator() = 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<HttpCookieManager> {
public: public:
typedef std::shared_ptr<CookieManager> Ptr; typedef std::shared_ptr<HttpCookieManager> Ptr;
friend class CookieData; friend class HttpServerCookie;
~CookieManager(); ~HttpCookieManager();
/** /**
* 获取单例 * 获取单例
*/ */
static CookieManager &Instance(); static HttpCookieManager &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(); HttpCookieManager();
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;
CookieGeneator _geneator; RandStrGeneator _geneator;
}; };
}//namespace mediakit
#endif //SRC_HTTP_COOKIEMANAGER_H #endif //SRC_HTTP_COOKIEMANAGER_H
...@@ -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, kMaxClientPerUid); auto cookie_str = HttpCookieManager::Instance().getOldestCookie(kCookieName,uid);
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);
......
...@@ -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 "HttpCookieManager.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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论