diff --git a/class/core/config_api.py b/class/core/config_api.py index 876ddbd1e..9924f5c5a 100755 --- a/class/core/config_api.py +++ b/class/core/config_api.py @@ -490,6 +490,18 @@ class config_api: 'id,type,uid,log,addtime').select() return mw.returnJson(False, 'ok', data) + def checkPanelToken(self): + api_file = self.__api_addr + if not os.path.exists(api_file): + return False, '' + + tmp = mw.readFile(api_file) + data = json.loads(tmp) + if data['open']: + return True, data + else: + return False, '' + def getPanelTokenApi(self): api_file = self.__api_addr diff --git a/plugins/php/install.sh b/plugins/php/install.sh index 05d325931..5442719fb 100755 --- a/plugins/php/install.sh +++ b/plugins/php/install.sh @@ -63,6 +63,7 @@ if [ "${action}" == "install" ] && [ -d ${serverPath}/php/${type} ];then cd ${rootPath}/plugins/php/versions/common && bash intl.sh install ${type} cd ${rootPath}/plugins/php/versions/common && bash mcrypt.sh install ${type} cd ${rootPath}/plugins/php/versions/common && bash openssl.sh install ${type} + cd ${rootPath}/plugins/php/versions/common && bash bcmath.sh install ${type} cd ${rootPath}/plugins/php/versions/common && bash gettext.sh install ${type} cd ${rootPath}/plugins/php/versions/common && bash redis.sh install ${type} cd ${rootPath}/plugins/php/versions/common && bash memcached.sh install ${type} diff --git a/route/__init__.py b/route/__init__.py index 582069994..e7a96be56 100755 --- a/route/__init__.py +++ b/route/__init__.py @@ -133,8 +133,6 @@ def funConvert(fun): func += suf return func -# Flask请求勾子 - def sendAuthenticated(): # 发送http认证信息 @@ -148,6 +146,7 @@ def sendAuthenticated(): @app.before_request def requestCheck(): + # Flask请求勾子 if app.config['BASIC_AUTH_OPEN']: auth = request.authorization if request.path in ['/download', '/hook', '/down']: @@ -407,9 +406,49 @@ def login_temp_user(token): return redirect('/') -@app.route('/api', methods=['POST', 'GET']) +@app.route('/api//', methods=['POST', 'GET']) def api(reqClass=None, reqAction=None, reqData=None): - pass + + comReturn = common.local() + if comReturn: + return comReturn + + import config_api + isOk, data = config_api.config_api().checkPanelToken() + if not isOk: + return mw.returnJson(False, '未开启API') + + request_time = request.form.get('request_time', '') + request_token = request.form.get('request_token', '') + request_ip = request.remote_addr + + token_md5 = mw.md5(str(request_time) + mw.md5(data['token_crypt'])) + + if not (token_md5 == request_token): + return mw.returnJson(False, '密钥错误') + + if not mw.inArray(data['limit_addr'], request_ip): + return mw.returnJson(False, '非法请求') + + if reqClass == None: + return mw.returnJson(False, '请指定请求方法类') + + if reqAction == None: + return mw.returnJson(False, '请指定请求方法') + + classFile = ('config_api', 'crontab_api', 'files_api', 'firewall_api', + 'plugins_api', 'system_api', 'site_api', 'task_api') + className = reqClass + '_api' + if not className in classFile: + return "external api request error" + + eval_str = "__import__('" + className + "')." + className + '()' + newInstance = eval(eval_str) + + try: + return publicObject(newInstance, reqAction) + except Exception as e: + return mw.getTracebackInfo() @app.route('//', methods=['POST', 'GET']) @@ -467,14 +506,14 @@ def index(reqClass=None, reqAction=None, reqData=None): return render_template(reqClass + '.html', data=data) if not isLogined(): - return 'request error!' + return 'error request!' # API请求 classFile = ('config_api', 'crontab_api', 'files_api', 'firewall_api', 'plugins_api', 'system_api', 'site_api', 'task_api') className = reqClass + '_api' if not className in classFile: - return "api request error" + return "api error request" eval_str = "__import__('" + className + "')." + className + '()' newInstance = eval(eval_str) diff --git a/version/api/mw_api.php b/version/api/mw_api.php new file mode 100755 index 000000000..4096d8fdf --- /dev/null +++ b/version/api/mw_api.php @@ -0,0 +1,94 @@ +MW_PANEL = $mw_panel; + } + + if ($mw_key) { + $this->MW_KEY = $mw_key; + } + } + + /** + * 发起POST请求 + * @param String $url 目标网填,带http:// + * @param Array|String $data 欲提交的数据 + * @return string + */ + private function httpPostCookie($url, $data, $timeout = 60) { + //定义cookie保存位置 + $cookie_file = './' . md5($this->MW_PANEL) . '.cookie'; + if (!file_exists($cookie_file)) { + $fp = fopen($cookie_file, 'w+'); + fclose($fp); + } + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file); + curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + $output = curl_exec($ch); + curl_close($ch); + return $output; + } + + /** + * 构造带有签名的关联数组 + */ + private function getKeyData() { + $now_time = time(); + $ready_data = array( + 'request_token' => md5($now_time . '' . md5($this->MW_KEY)), + 'request_time' => $now_time, + ); + return $ready_data; + } + + //示例取面板日志 + public function getLogsList() { + //拼接URL地址 + $url = $this->MW_PANEL . '/api/firewall/get_log_list'; + + //准备POST数据 + $post_data = $this->getKeyData(); //取签名 + $post_data['p'] = '1'; + $post_data['limit'] = 10; + + //请求面板接口 + $result = $this->httpPostCookie($url, $post_data); + + //解析JSON数据 + $data = json_decode($result, true); + return $data; + } + +} + +//实例化对象 +$api = new mwApi(); +//获取面板日志 +$rdata = $api->getLogsList(); + +// var_dump($rdata); +//输出JSON数据到浏览器 +echo json_encode($rdata); + +?> \ No newline at end of file diff --git a/version/api/mw_api.py b/version/api/mw_api.py new file mode 100755 index 000000000..19399402f --- /dev/null +++ b/version/api/mw_api.py @@ -0,0 +1,122 @@ +# coding: utf-8 +# +----------------------------------------------------------------------------------- +# | MW Linux面板 +# +----------------------------------------------------------------------------------- +# | Copyright (c) 2015-2099 MW(http://github.com/midoks/mdserver) All rights reserved. +# +----------------------------------------------------------------------------------- +# | Author: midoks +# +----------------------------------------------------------------------------------- + +#------------------------------ +# API-Demo of Python +#------------------------------ +import time +import hashlib +import sys +import os +import json + + +class mwApi: + __MW_KEY = 'j7GQhzNcBV4KU9QKYPXvtjSzCcmfkc0e' + __MW_PANEL = 'http://127.0.0.1:7200' + + # 如果希望多台面板,可以在实例化对象时,将面板地址与密钥传入 + def __init__(self, mw_panel=None, mw_key=None): + if mw_panel: + self.__MW_PANEL = mw_panel + self.__MW_KEY = mw_key + + # 计算MD5 + def __get_md5(self, s): + m = hashlib.md5() + m.update(s.encode('utf-8')) + return m.hexdigest() + + # 构造带有签名的关联数组 + def __get_key_data(self): + now_time = int(time.time()) + ready_data = { + 'request_token': self.__get_md5(str(now_time) + '' + self.__get_md5(self.__MW_KEY)), + 'request_time': now_time + } + return ready_data + + # 发送POST请求并保存Cookie + #@url 被请求的URL地址(必需) + #@data POST参数,可以是字符串或字典(必需) + #@timeout 超时时间默认1800秒 + # return string + def __http_post_cookie(self, url, p_data, timeout=1800): + cookie_file = './' + self.__get_md5(self.__MW_PANEL) + '.cookie' + if sys.version_info[0] == 2: + # Python2 + import urllib + import urllib2 + import ssl + import cookielib + + # 创建cookie对象 + cookie_obj = cookielib.MozillaCookieJar(cookie_file) + + # 加载已保存的cookie + if os.path.exists(cookie_file): + cookie_obj.load(cookie_file, ignore_discard=True, + ignore_expires=True) + + ssl._create_default_https_context = ssl._create_unverified_context + + data = urllib.urlencode(p_data) + req = urllib2.Request(url, data) + opener = urllib2.build_opener( + urllib2.HTTPCookieProcessor(cookie_obj)) + response = opener.open(req, timeout=timeout) + + # 保存cookie + cookie_obj.save(ignore_discard=True, ignore_expires=True) + return response.read() + else: + # Python3 + import urllib.request + import ssl + import http.cookiejar + cookie_obj = http.cookiejar.MozillaCookieJar(cookie_file) + cookie_obj.load(cookie_file, ignore_discard=True, + ignore_expires=True) + handler = urllib.request.HTTPCookieProcessor(cookie_obj) + data = urllib.parse.urlencode(p_data).encode('utf-8') + req = urllib.request.Request(url, data) + opener = urllib.request.build_opener(handler) + response = opener.open(req, timeout=timeout) + cookie_obj.save(ignore_discard=True, ignore_expires=True) + result = response.read() + if type(result) == bytes: + result = result.decode('utf-8') + return result + + # 取面板日志 + def getLogs(self): + # 拼接URL地址 + url = self.__MW_PANEL + '/api/firewall/get_log_list' + + # 准备POST数据 + post_data = self.__get_key_data() # 取签名 + post_data['limit'] = 10 + post_data['p'] = '1' + + # 请求面板接口 + result = self.__http_post_cookie(url, post_data) + + # 解析JSON数据 + return json.loads(result) + + +if __name__ == '__main__': + # 实例化宝塔API对象 + api = mwApi() + + # 调用get_logs方法 + rdata = api.getLogs() + + # 打印响应数据 + print(rdata)