Commit c7cc082d by xiongziliang

http文件鉴权支持自定义错误提示

parent cfbdda06
...@@ -673,34 +673,23 @@ void installWebApi() { ...@@ -673,34 +673,23 @@ void installWebApi() {
}; };
API_REGIST(hook,on_http_access,{ API_REGIST(hook,on_http_access,{
#if 0
//能访问根目录以及根目录下所有文件10分钟
val["path"] = "/";
val["second"] = 10 * 60;
#else
//在这里根据allArgs["params"](url参数)来判断该http客户端是否有权限访问该文件 //在这里根据allArgs["params"](url参数)来判断该http客户端是否有权限访问该文件
if(!checkAccess(allArgs["params"])){ if(!checkAccess(allArgs["params"])){
//无访问权限 //无访问权限
val["err"] = "无访问权限";
//仅限制访问当前目录
val["path"] = ""; val["path"] = "";
//标记该客户端无权限1分钟,1分钟之内它凭此cookie访问将都无权限 //标记该客户端无权限1分钟
//如果客户端不支持cookie,那么可以根据url参数来追踪用户,请参考kBroadcastTrackHttpClient事件
//如果服务器未处理kBroadcastTrackHttpClient事件,那么ZLMediaKit会根据ip和端口追踪用户
val["second"] = 60; val["second"] = 60;
return; return;
} }
//只能访问本文件,且只授权10分钟,访问其他文件都要另外授权 //可以访问
if(allArgs["is_dir"].as<bool>()){ val["err"] = "";
//访问的是目录,该授权cookie只对该目录有效 //只能访问当前目录
val["path"] = (string)allArgs["path"]; val["path"] = "";
}else{ //该http客户端用户被授予10分钟的访问权限,该权限仅限访问当前目录
//访问的是文件,那么我们授予客户端访问所在目录的权限
string dir = allArgs["path"].substr(0,allArgs["path"].rfind("/") + 1);
val["path"] = dir;
}
//该http客户端用户被授予10分钟的访问权限,该权限仅限访问特定目录
val["second"] = 10 * 60; val["second"] = 10 * 60;
#endif
}); });
......
...@@ -399,13 +399,13 @@ void installWebHook(){ ...@@ -399,13 +399,13 @@ void installWebHook(){
NoticeCenter::Instance().addListener(nullptr,Broadcast::kBroadcastHttpAccess,[](BroadcastHttpAccessArgs){ NoticeCenter::Instance().addListener(nullptr,Broadcast::kBroadcastHttpAccess,[](BroadcastHttpAccessArgs){
if(sender.get_peer_ip() == "127.0.0.1" && args._param_strs == hook_adminparams){ if(sender.get_peer_ip() == "127.0.0.1" && args._param_strs == hook_adminparams){
//如果是本机或超级管理员访问,那么不做访问鉴权;权限有效期1个小时 //如果是本机或超级管理员访问,那么不做访问鉴权;权限有效期1个小时
invoker("/",60 * 60); invoker("","",60 * 60);
return; return;
} }
if(!hook_enable || hook_http_access.empty()){ if(!hook_enable || hook_http_access.empty()){
//未开启http文件访问鉴权,那么允许访问,但是每次访问都要鉴权; //未开启http文件访问鉴权,那么允许访问,但是每次访问都要鉴权;
//因为后续随时都可能开启鉴权(重载配置文件后可能重新开启鉴权) //因为后续随时都可能开启鉴权(重载配置文件后可能重新开启鉴权)
invoker("/",0); invoker("","",0);
return; return;
} }
...@@ -423,15 +423,13 @@ void installWebHook(){ ...@@ -423,15 +423,13 @@ void installWebHook(){
do_http_hook(hook_http_access,body, [invoker](const Value &obj,const string &err){ do_http_hook(hook_http_access,body, [invoker](const Value &obj,const string &err){
if(!err.empty()){ if(!err.empty()){
//如果接口访问失败,那么仅限本次没有访问http服务器的权限 //如果接口访问失败,那么仅限本次没有访问http服务器的权限
invoker("",0); invoker(err,"",0);
return; return;
} }
//path参数是该客户端能访问的顶端目录,该目录下的所有文件它都能访问 //err参数代表不能访问的原因,空则代表可以访问
//second参数规定该cookie超时时间,超过这个时间后,用户需要重新鉴权 //path参数是该客户端能访问或被禁止的顶端目录,如果path为空字符串,则表述为当前目录
//如果path为空字符串,则为禁止访问任何目录 //second参数规定该cookie超时时间,如果second为0,本次鉴权结果不缓存
//如果second为0,本次鉴权结果不缓存 invoker(obj["err"].asString(),obj["path"].asString(),obj["second"].asInt());
//如果被禁止访问文件,在cookie有效期内,假定再次访问的url参数变了,那么也能立即触发重新鉴权操作
invoker(obj["path"].asString(),obj["second"].asInt());
}); });
}); });
} }
......
...@@ -76,6 +76,10 @@ bool HttpServerCookie::isExpired() { ...@@ -76,6 +76,10 @@ bool HttpServerCookie::isExpired() {
return _ticker.elapsedTime() > _max_elapsed * 1000; return _ticker.elapsedTime() > _max_elapsed * 1000;
} }
std::shared_ptr<lock_guard<mutex> > HttpServerCookie::getLock(){
return std::make_shared<lock_guard<mutex> >(_mtx);
}
string HttpServerCookie::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;
...@@ -105,7 +109,7 @@ void HttpCookieManager::onManager() { ...@@ -105,7 +109,7 @@ void HttpCookieManager::onManager() {
for (auto it_cookie = it_name->second.begin() ; it_cookie != it_name->second.end() ; ){ for (auto it_cookie = it_name->second.begin() ; it_cookie != it_name->second.end() ; ){
if(it_cookie->second->isExpired()){ if(it_cookie->second->isExpired()){
//cookie过期,移除记录 //cookie过期,移除记录
WarnL << it_cookie->second->getUid() << " cookie过期"; DebugL << it_cookie->second->getUid() << " cookie过期:" << it_cookie->second->getCookie();
it_cookie = it_name->second.erase(it_cookie); it_cookie = it_name->second.erase(it_cookie);
continue; continue;
} }
...@@ -114,7 +118,7 @@ void HttpCookieManager::onManager() { ...@@ -114,7 +118,7 @@ void HttpCookieManager::onManager() {
if(it_name->second.empty()){ if(it_name->second.empty()){
//该类型下没有任何cooki记录,移除之 //该类型下没有任何cooki记录,移除之
WarnL << "该path下没有任何cooki记录:" << it_name->first; DebugL << "该path下没有任何cooki记录:" << it_name->first;
it_name = _map_cookie.erase(it_name); it_name = _map_cookie.erase(it_name);
continue; continue;
} }
...@@ -152,6 +156,7 @@ HttpServerCookie::Ptr HttpCookieManager::getCookie(const string &cookie_name,con ...@@ -152,6 +156,7 @@ HttpServerCookie::Ptr HttpCookieManager::getCookie(const string &cookie_name,con
} }
if(it_cookie->second->isExpired()){ if(it_cookie->second->isExpired()){
//cookie过期 //cookie过期
DebugL << "cookie过期:" << it_cookie->second->getCookie();
it_name->second.erase(it_cookie); it_name->second.erase(it_cookie);
return nullptr; return nullptr;
} }
......
...@@ -102,6 +102,12 @@ public: ...@@ -102,6 +102,12 @@ public:
* @return * @return
*/ */
bool isExpired(); bool isExpired();
/**
* 获取区域锁
* @return
*/
std::shared_ptr<lock_guard<mutex> > getLock();
private: private:
string cookieExpireTime() const ; string cookieExpireTime() const ;
private: private:
...@@ -110,6 +116,7 @@ private: ...@@ -110,6 +116,7 @@ private:
string _cookie_uuid; string _cookie_uuid;
uint64_t _max_elapsed; uint64_t _max_elapsed;
Ticker _ticker; Ticker _ticker;
mutex _mtx;
std::weak_ptr<HttpCookieManager> _manager; std::weak_ptr<HttpCookieManager> _manager;
}; };
......
...@@ -52,7 +52,12 @@ public: ...@@ -52,7 +52,12 @@ public:
const KeyValue &headerOut, const KeyValue &headerOut,
const string &contentOut)> HttpResponseInvoker; const string &contentOut)> HttpResponseInvoker;
typedef std::function<void(const string &accessPath, int cookieLifeSecond)> HttpAccessPathInvoker; /**
* @param errMsg 如果为空,则代表鉴权通过,否则为错误提示
* @param accessPath 运行或禁止访问的根目录
* @param cookieLifeSecond 鉴权cookie有效期
**/
typedef std::function<void(const string &errMsg,const string &accessPath, int cookieLifeSecond)> HttpAccessPathInvoker;
HttpSession(const Socket::Ptr &pSock); HttpSession(const Socket::Ptr &pSock);
virtual ~HttpSession(); virtual ~HttpSession();
...@@ -125,7 +130,7 @@ private: ...@@ -125,7 +130,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 HttpServerCookie::Ptr &cookie)> &callback); inline void canAccessPath(const string &path,bool is_dir,const function<void(const string &errMsg,const HttpServerCookie::Ptr &cookie)> &callback);
/** /**
* 获取用户唯一识别id * 获取用户唯一识别id
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论