mirror of https://github.com/flucont/btcloud.git
2 Commits
57cbf9315c
...
aba885f434
Author | SHA1 | Message | Date |
---|---|---|---|
flucout | aba885f434 |
update
|
4 months ago |
flucout | 5e1f19de53 |
支持生成自签SSL证书
|
4 months ago |
28 changed files with 785 additions and 514 deletions
-
29app/command/Clean.php
-
96app/common.php
-
33app/controller/Admin.php
-
56app/controller/Api.php
-
10app/lib/BtPlugins.php
-
484app/lib/Btapi.php
-
1app/lib/ThirdPlugins.php
-
52app/middleware/AuthAdmin.php
-
38app/middleware/CheckAdmin.php
-
2app/middleware/LoadConfig.php
-
48app/middleware/RefererCheck.php
-
31app/script/cacert.sh
-
2app/view/admin/deplist.html
-
118app/view/admin/index.html
-
17app/view/admin/layout.html
-
6app/view/admin/list.html
-
6app/view/admin/log.html
-
12app/view/admin/login.html
-
13app/view/admin/plugins.html
-
6app/view/admin/pluginswin.html
-
6app/view/admin/record.html
-
2app/view/admin/set.html
-
86app/view/admin/ssl.html
-
118app/view/dispatch_jump.html
-
6app/view/index/download.html
-
2app/view/install/index.html
-
12install.sql
-
7route/app.php
@ -1,243 +1,243 @@ |
|||||
<?php |
|
||||
|
|
||||
namespace app\lib; |
|
||||
|
|
||||
use Exception; |
|
||||
|
|
||||
class Btapi |
|
||||
{ |
|
||||
private $BT_KEY; //接口密钥
|
|
||||
private $BT_PANEL; //面板地址
|
|
||||
|
|
||||
public function __construct($bt_panel, $bt_key){ |
|
||||
$this->BT_PANEL = $bt_panel; |
|
||||
$this->BT_KEY = $bt_key; |
|
||||
} |
|
||||
|
|
||||
//获取面板配置信息
|
|
||||
public function get_config(){ |
|
||||
$url = $this->BT_PANEL.'/config?action=get_config'; |
|
||||
|
|
||||
$p_data = $this->GetKeyData(); |
|
||||
|
|
||||
$result = $this->curl($url,$p_data); |
|
||||
|
|
||||
$data = json_decode($result,true); |
|
||||
return $data; |
|
||||
} |
|
||||
|
|
||||
//获取已登录用户信息
|
|
||||
public function get_user_info(){ |
|
||||
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=get_user_info'; |
|
||||
|
|
||||
$p_data = $this->GetKeyData(); |
|
||||
|
|
||||
$result = $this->curl($url,$p_data); |
|
||||
|
|
||||
$data = json_decode($result,true); |
|
||||
return $data; |
|
||||
} |
|
||||
|
|
||||
//从云端获取插件列表
|
|
||||
public function get_plugin_list(){ |
|
||||
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=get_plugin_list'; |
|
||||
|
|
||||
$p_data = $this->GetKeyData(); |
|
||||
|
|
||||
$result = $this->curl($url,$p_data); |
|
||||
|
|
||||
$data = json_decode($result,true); |
|
||||
return $data; |
|
||||
} |
|
||||
|
|
||||
//下载插件包,返回文件路径
|
|
||||
public function get_plugin_filename($plugin_name, $version){ |
|
||||
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=download_plugin'; |
|
||||
|
|
||||
$p_data = $this->GetKeyData(); |
|
||||
$p_data['plugin_name'] = $plugin_name; |
|
||||
$p_data['version'] = $version; |
|
||||
|
|
||||
$result = $this->curl($url,$p_data); |
|
||||
|
|
||||
$data = json_decode($result,true); |
|
||||
return $data; |
|
||||
} |
|
||||
|
|
||||
//下载插件主程序文件,返回文件路径
|
|
||||
public function get_plugin_main_filename($plugin_name, $version){ |
|
||||
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=download_plugin_main'; |
|
||||
|
|
||||
$p_data = $this->GetKeyData(); |
|
||||
$p_data['plugin_name'] = $plugin_name; |
|
||||
$p_data['version'] = $version; |
|
||||
|
|
||||
$result = $this->curl($url,$p_data); |
|
||||
|
|
||||
$data = json_decode($result,true); |
|
||||
return $data; |
|
||||
} |
|
||||
|
|
||||
//解密插件主程序py代码,返回文件路径
|
|
||||
public function get_decode_plugin_main($plugin_name, $version){ |
|
||||
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=decode_plugin_main'; |
|
||||
|
|
||||
$p_data = $this->GetKeyData(); |
|
||||
$p_data['plugin_name'] = $plugin_name; |
|
||||
$p_data['version'] = $version; |
|
||||
|
|
||||
$result = $this->curl($url,$p_data); |
|
||||
|
|
||||
$data = json_decode($result,true); |
|
||||
return $data; |
|
||||
} |
|
||||
|
|
||||
//下载插件其他文件,返回文件路径
|
|
||||
public function get_plugin_other_filename($fname){ |
|
||||
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=download_plugin_other'; |
|
||||
|
|
||||
$p_data = $this->GetKeyData(); |
|
||||
$p_data['fname'] = $fname; |
|
||||
|
|
||||
$result = $this->curl($url,$p_data); |
|
||||
|
|
||||
$data = json_decode($result,true); |
|
||||
return $data; |
|
||||
} |
|
||||
|
|
||||
//下载文件
|
|
||||
public function download($filename, $localpath){ |
|
||||
$url = $this->BT_PANEL.'/download'; |
|
||||
|
|
||||
$p_data = $this->GetKeyData(); |
|
||||
$p_data['filename'] = $filename; |
|
||||
|
|
||||
$result = $this->curl_download($url.'?'.http_build_query($p_data), $localpath); |
|
||||
|
|
||||
return $result; |
|
||||
} |
|
||||
|
|
||||
//获取文件base64
|
|
||||
public function get_file($filename){ |
|
||||
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=get_file'; |
|
||||
|
|
||||
$p_data = $this->GetKeyData(); |
|
||||
$p_data['filename'] = $filename; |
|
||||
|
|
||||
$result = $this->curl($url,$p_data); |
|
||||
|
|
||||
$data = json_decode($result,true); |
|
||||
return $data; |
|
||||
} |
|
||||
|
|
||||
//购买第三方插件
|
|
||||
public function create_plugin_other_order($pid){ |
|
||||
$url = $this->BT_PANEL.'/auth?action=create_plugin_other_order'; |
|
||||
|
|
||||
$p_data = $this->GetKeyData(); |
|
||||
$p_data['pid'] = $pid; |
|
||||
$p_data['cycle'] = '999'; |
|
||||
$p_data['type'] = '0'; |
|
||||
|
|
||||
$result = $this->curl($url,$p_data); |
|
||||
|
|
||||
$data = json_decode($result,true); |
|
||||
return $data; |
|
||||
} |
|
||||
|
|
||||
//获取一键部署列表
|
|
||||
public function get_deplist(){ |
|
||||
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=get_deplist'; |
|
||||
|
|
||||
$p_data = $this->GetKeyData(); |
|
||||
|
|
||||
$result = $this->curl($url,$p_data); |
|
||||
|
|
||||
$data = json_decode($result,true); |
|
||||
return $data; |
|
||||
} |
|
||||
|
|
||||
//BTWAF-获取蜘蛛列表
|
|
||||
public function btwaf_getspiders(){ |
|
||||
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=btwaf_getspiders'; |
|
||||
|
|
||||
$p_data = $this->GetKeyData(); |
|
||||
|
|
||||
$result = $this->curl($url,$p_data); |
|
||||
$result = str_replace("\u0000", '', $result); |
|
||||
|
|
||||
$data = json_decode($result,true); |
|
||||
return $data; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
private function GetKeyData(){ |
|
||||
$now_time = time(); |
|
||||
$p_data = array( |
|
||||
'request_token' => md5($now_time.''.md5($this->BT_KEY)), |
|
||||
'request_time' => $now_time |
|
||||
); |
|
||||
return $p_data; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
private function curl($url, $data = null, $timeout = 60) |
|
||||
{ |
|
||||
//定义cookie保存位置
|
|
||||
$cookie_file=app()->getRuntimePath().md5($this->BT_PANEL).'.cookie'; |
|
||||
if(!file_exists($cookie_file)){ |
|
||||
touch($cookie_file); |
|
||||
} |
|
||||
|
|
||||
$ch = curl_init(); |
|
||||
curl_setopt($ch, CURLOPT_URL, $url); |
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); |
|
||||
if($data){ |
|
||||
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_SSL_VERIFYHOST, false); |
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); |
|
||||
$output = curl_exec($ch); |
|
||||
curl_close($ch); |
|
||||
return $output; |
|
||||
} |
|
||||
|
|
||||
private function curl_download($url, $localpath, $timeout = 300) |
|
||||
{ |
|
||||
//定义cookie保存位置
|
|
||||
$cookie_file=app()->getRuntimePath().md5($this->BT_PANEL).'.cookie'; |
|
||||
if(!file_exists($cookie_file)){ |
|
||||
touch($cookie_file); |
|
||||
} |
|
||||
|
|
||||
$ch = curl_init(); |
|
||||
curl_setopt($ch, CURLOPT_URL, $url); |
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); |
|
||||
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file); |
|
||||
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file); |
|
||||
$fp = fopen($localpath, 'w+'); |
|
||||
curl_setopt($ch, CURLOPT_FILE, $fp); |
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); |
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); |
|
||||
curl_exec($ch); |
|
||||
if (curl_errno($ch)) { |
|
||||
$message = curl_error($ch); |
|
||||
curl_close($ch); |
|
||||
fclose($fp); |
|
||||
throw new Exception('下载文件失败:'.$message); |
|
||||
} |
|
||||
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); |
|
||||
if($httpcode>299){ |
|
||||
curl_close($ch); |
|
||||
fclose($fp); |
|
||||
throw new Exception('下载文件失败:HTTPCODE-'.$httpcode); |
|
||||
} |
|
||||
curl_close($ch); |
|
||||
fclose($fp); |
|
||||
return true; |
|
||||
} |
|
||||
|
<?php |
||||
|
|
||||
|
namespace app\lib; |
||||
|
|
||||
|
use Exception; |
||||
|
|
||||
|
class Btapi |
||||
|
{ |
||||
|
private $BT_KEY; //接口密钥
|
||||
|
private $BT_PANEL; //面板地址
|
||||
|
|
||||
|
public function __construct($bt_panel, $bt_key){ |
||||
|
$this->BT_PANEL = $bt_panel; |
||||
|
$this->BT_KEY = $bt_key; |
||||
|
} |
||||
|
|
||||
|
//获取面板配置信息
|
||||
|
public function get_config(){ |
||||
|
$url = $this->BT_PANEL.'/config?action=get_config'; |
||||
|
|
||||
|
$p_data = $this->GetKeyData(); |
||||
|
|
||||
|
$result = $this->curl($url,$p_data); |
||||
|
|
||||
|
$data = json_decode($result,true); |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
//获取已登录用户信息
|
||||
|
public function get_user_info(){ |
||||
|
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=get_user_info'; |
||||
|
|
||||
|
$p_data = $this->GetKeyData(); |
||||
|
|
||||
|
$result = $this->curl($url,$p_data); |
||||
|
|
||||
|
$data = json_decode($result,true); |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
//从云端获取插件列表
|
||||
|
public function get_plugin_list(){ |
||||
|
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=get_plugin_list'; |
||||
|
|
||||
|
$p_data = $this->GetKeyData(); |
||||
|
|
||||
|
$result = $this->curl($url,$p_data); |
||||
|
|
||||
|
$data = json_decode($result,true); |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
//下载插件包,返回文件路径
|
||||
|
public function get_plugin_filename($plugin_name, $version){ |
||||
|
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=download_plugin'; |
||||
|
|
||||
|
$p_data = $this->GetKeyData(); |
||||
|
$p_data['plugin_name'] = $plugin_name; |
||||
|
$p_data['version'] = $version; |
||||
|
|
||||
|
$result = $this->curl($url,$p_data); |
||||
|
|
||||
|
$data = json_decode($result,true); |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
//下载插件主程序文件,返回文件路径
|
||||
|
public function get_plugin_main_filename($plugin_name, $version){ |
||||
|
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=download_plugin_main'; |
||||
|
|
||||
|
$p_data = $this->GetKeyData(); |
||||
|
$p_data['plugin_name'] = $plugin_name; |
||||
|
$p_data['version'] = $version; |
||||
|
|
||||
|
$result = $this->curl($url,$p_data); |
||||
|
|
||||
|
$data = json_decode($result,true); |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
//解密插件主程序py代码,返回文件路径
|
||||
|
public function get_decode_plugin_main($plugin_name, $version){ |
||||
|
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=decode_plugin_main'; |
||||
|
|
||||
|
$p_data = $this->GetKeyData(); |
||||
|
$p_data['plugin_name'] = $plugin_name; |
||||
|
$p_data['version'] = $version; |
||||
|
|
||||
|
$result = $this->curl($url,$p_data); |
||||
|
|
||||
|
$data = json_decode($result,true); |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
//下载插件其他文件,返回文件路径
|
||||
|
public function get_plugin_other_filename($fname){ |
||||
|
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=download_plugin_other'; |
||||
|
|
||||
|
$p_data = $this->GetKeyData(); |
||||
|
$p_data['fname'] = $fname; |
||||
|
|
||||
|
$result = $this->curl($url,$p_data); |
||||
|
|
||||
|
$data = json_decode($result,true); |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
//下载文件
|
||||
|
public function download($filename, $localpath){ |
||||
|
$url = $this->BT_PANEL.'/download'; |
||||
|
|
||||
|
$p_data = $this->GetKeyData(); |
||||
|
$p_data['filename'] = $filename; |
||||
|
|
||||
|
$result = $this->curl_download($url.'?'.http_build_query($p_data), $localpath); |
||||
|
|
||||
|
return $result; |
||||
|
} |
||||
|
|
||||
|
//获取文件base64
|
||||
|
public function get_file($filename){ |
||||
|
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=get_file'; |
||||
|
|
||||
|
$p_data = $this->GetKeyData(); |
||||
|
$p_data['filename'] = $filename; |
||||
|
|
||||
|
$result = $this->curl($url,$p_data); |
||||
|
|
||||
|
$data = json_decode($result,true); |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
//购买第三方插件
|
||||
|
public function create_plugin_other_order($pid){ |
||||
|
$url = $this->BT_PANEL.'/auth?action=create_plugin_other_order'; |
||||
|
|
||||
|
$p_data = $this->GetKeyData(); |
||||
|
$p_data['pid'] = $pid; |
||||
|
$p_data['cycle'] = '999'; |
||||
|
$p_data['type'] = '0'; |
||||
|
|
||||
|
$result = $this->curl($url,$p_data); |
||||
|
|
||||
|
$data = json_decode($result,true); |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
//获取一键部署列表
|
||||
|
public function get_deplist(){ |
||||
|
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=get_deplist'; |
||||
|
|
||||
|
$p_data = $this->GetKeyData(); |
||||
|
|
||||
|
$result = $this->curl($url,$p_data); |
||||
|
|
||||
|
$data = json_decode($result,true); |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
//BTWAF-获取蜘蛛列表
|
||||
|
public function btwaf_getspiders(){ |
||||
|
$url = $this->BT_PANEL.'/plugin?action=a&name=kaixin&s=btwaf_getspiders'; |
||||
|
|
||||
|
$p_data = $this->GetKeyData(); |
||||
|
|
||||
|
$result = $this->curl($url,$p_data); |
||||
|
$result = str_replace("\u0000", '', $result); |
||||
|
|
||||
|
$data = json_decode($result,true); |
||||
|
return $data; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
private function GetKeyData(){ |
||||
|
$now_time = time(); |
||||
|
$p_data = array( |
||||
|
'request_token' => md5($now_time.''.md5($this->BT_KEY)), |
||||
|
'request_time' => $now_time |
||||
|
); |
||||
|
return $p_data; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
private function curl($url, $data = null, $timeout = 60) |
||||
|
{ |
||||
|
//定义cookie保存位置
|
||||
|
$cookie_file=app()->getRuntimePath().md5($this->BT_PANEL).'.cookie'; |
||||
|
if(!file_exists($cookie_file)){ |
||||
|
touch($cookie_file); |
||||
|
} |
||||
|
|
||||
|
$ch = curl_init(); |
||||
|
curl_setopt($ch, CURLOPT_URL, $url); |
||||
|
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); |
||||
|
if($data){ |
||||
|
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_SSL_VERIFYHOST, false); |
||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); |
||||
|
$output = curl_exec($ch); |
||||
|
curl_close($ch); |
||||
|
return $output; |
||||
|
} |
||||
|
|
||||
|
private function curl_download($url, $localpath, $timeout = 300) |
||||
|
{ |
||||
|
//定义cookie保存位置
|
||||
|
$cookie_file=app()->getRuntimePath().md5($this->BT_PANEL).'.cookie'; |
||||
|
if(!file_exists($cookie_file)){ |
||||
|
touch($cookie_file); |
||||
|
} |
||||
|
|
||||
|
$ch = curl_init(); |
||||
|
curl_setopt($ch, CURLOPT_URL, $url); |
||||
|
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); |
||||
|
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file); |
||||
|
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file); |
||||
|
$fp = fopen($localpath, 'w+'); |
||||
|
curl_setopt($ch, CURLOPT_FILE, $fp); |
||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); |
||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); |
||||
|
curl_exec($ch); |
||||
|
if (curl_errno($ch)) { |
||||
|
$message = curl_error($ch); |
||||
|
curl_close($ch); |
||||
|
fclose($fp); |
||||
|
throw new Exception('下载文件失败:'.$message); |
||||
|
} |
||||
|
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); |
||||
|
if($httpcode>299){ |
||||
|
curl_close($ch); |
||||
|
fclose($fp); |
||||
|
throw new Exception('下载文件失败:HTTPCODE-'.$httpcode); |
||||
|
} |
||||
|
curl_close($ch); |
||||
|
fclose($fp); |
||||
|
return true; |
||||
|
} |
||||
} |
} |
@ -1,26 +1,26 @@ |
|||||
<?php |
|
||||
declare (strict_types=1); |
|
||||
|
|
||||
namespace app\middleware; |
|
||||
|
|
||||
|
|
||||
class AuthAdmin |
|
||||
{ |
|
||||
public function handle($request, \Closure $next) |
|
||||
{ |
|
||||
$islogin = false; |
|
||||
$cookie = cookie('admin_token'); |
|
||||
if($cookie){ |
|
||||
$token=authcode($cookie, 'DECODE', config_get('syskey')); |
|
||||
if($token){ |
|
||||
list($user, $sid, $expiretime) = explode("\t", $token); |
|
||||
$session=md5(config_get('admin_username').config_get('admin_password')); |
|
||||
if($session==$sid && $expiretime>time()) { |
|
||||
$islogin = true; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
request()->islogin = $islogin; |
|
||||
return $next($request); |
|
||||
} |
|
||||
} |
|
||||
|
<?php |
||||
|
declare (strict_types=1); |
||||
|
|
||||
|
namespace app\middleware; |
||||
|
|
||||
|
|
||||
|
class AuthAdmin |
||||
|
{ |
||||
|
public function handle($request, \Closure $next) |
||||
|
{ |
||||
|
$islogin = false; |
||||
|
$cookie = cookie('admin_token'); |
||||
|
if($cookie){ |
||||
|
$token=authcode($cookie, 'DECODE', config_get('syskey')); |
||||
|
if($token){ |
||||
|
list($user, $sid, $expiretime) = explode("\t", $token); |
||||
|
$session=md5(config_get('admin_username').config_get('admin_password')); |
||||
|
if($session==$sid && $expiretime>time()) { |
||||
|
$islogin = true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
request()->islogin = $islogin; |
||||
|
return $next($request); |
||||
|
} |
||||
|
} |
@ -1,19 +1,19 @@ |
|||||
<?php |
|
||||
declare (strict_types=1); |
|
||||
|
|
||||
namespace app\middleware; |
|
||||
|
|
||||
|
|
||||
class CheckAdmin |
|
||||
{ |
|
||||
public function handle($request, \Closure $next) |
|
||||
{ |
|
||||
if (!request()->islogin) { |
|
||||
if ($request->isAjax() || !$request->isGet()) { |
|
||||
return json(['code'=>-1, 'msg'=>'未登录'])->code(401); |
|
||||
} |
|
||||
return redirect((string)url('/admin/login')); |
|
||||
} |
|
||||
return $next($request); |
|
||||
} |
|
||||
} |
|
||||
|
<?php |
||||
|
declare (strict_types=1); |
||||
|
|
||||
|
namespace app\middleware; |
||||
|
|
||||
|
|
||||
|
class CheckAdmin |
||||
|
{ |
||||
|
public function handle($request, \Closure $next) |
||||
|
{ |
||||
|
if (!request()->islogin) { |
||||
|
if ($request->isAjax() || !$request->isGet()) { |
||||
|
return json(['code'=>-1, 'msg'=>'未登录'])->code(401); |
||||
|
} |
||||
|
return redirect((string)url('/admin/login')); |
||||
|
} |
||||
|
return $next($request); |
||||
|
} |
||||
|
} |
@ -1,24 +1,24 @@ |
|||||
<?php |
|
||||
declare (strict_types=1); |
|
||||
|
|
||||
namespace app\middleware; |
|
||||
|
|
||||
use think\facade\View; |
|
||||
|
|
||||
class RefererCheck |
|
||||
{ |
|
||||
/** |
|
||||
* 处理请求 |
|
||||
* |
|
||||
* @param \think\Request $request |
|
||||
* @param \Closure $next |
|
||||
* @return Response |
|
||||
*/ |
|
||||
public function handle($request, \Closure $next) |
|
||||
{ |
|
||||
if(!checkRefererHost()){ |
|
||||
return response('Access Denied', 403); |
|
||||
} |
|
||||
return $next($request); |
|
||||
} |
|
||||
} |
|
||||
|
<?php |
||||
|
declare (strict_types=1); |
||||
|
|
||||
|
namespace app\middleware; |
||||
|
|
||||
|
use think\facade\View; |
||||
|
|
||||
|
class RefererCheck |
||||
|
{ |
||||
|
/** |
||||
|
* 处理请求 |
||||
|
* |
||||
|
* @param \think\Request $request |
||||
|
* @param \Closure $next |
||||
|
* @return Response |
||||
|
*/ |
||||
|
public function handle($request, \Closure $next) |
||||
|
{ |
||||
|
if(!checkRefererHost()){ |
||||
|
return response('Access Denied', 403); |
||||
|
} |
||||
|
return $next($request); |
||||
|
} |
||||
|
} |
@ -0,0 +1,31 @@ |
|||||
|
#!/bin/bash |
||||
|
|
||||
|
OPENSSL_CHECK=$(which openssl) |
||||
|
if [ "$?" != "0" ]; then |
||||
|
echo "未安装OpenSSL" |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
if [ ! -f ca.key ] && [ ! -f ca.crt ]; then |
||||
|
openssl genrsa -out ca.key 2048 |
||||
|
openssl req -new -x509 -utf8 -days 3650 -extensions v3_ca -subj "/C=CN/O=宝塔面板/CN=宝塔面板" -key ca.key -out ca.crt |
||||
|
fi |
||||
|
|
||||
|
openssl genrsa -out server.key 2048 |
||||
|
openssl req -new -nodes -key server.key -subj "/C=CN/O=BTPanel/CN=BTPanel" -out server.csr |
||||
|
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650 -extensions req_ext |
||||
|
|
||||
|
cat ca.crt >> server.crt |
||||
|
|
||||
|
openssl pkcs12 -export -out baota_root.pfx -inkey server.key -in server.crt -password pass: |
||||
|
if [ "$?" != "0" ]; then |
||||
|
echo "生成CA根证书失败" |
||||
|
exit 1 |
||||
|
fi |
||||
|
|
||||
|
mkdir -p ../../public/ssl |
||||
|
\cp baota_root.pfx ../../public/ssl/baota_root.pfx |
||||
|
\cp ca.crt ../../public/ssl/baota_root.crt |
||||
|
rm -f server.crt server.key server.csr |
||||
|
|
||||
|
echo "生成CA根证书成功" |
@ -1,60 +1,60 @@ |
|||||
{extend name="admin/layout" /} |
|
||||
{block name="title"}宝塔第三方云端管理中心{/block} |
|
||||
{block name="main"} |
|
||||
<style> |
|
||||
.table>tbody>tr>td{white-space: normal;} |
|
||||
.query-title { |
|
||||
background-color:#f5fafe; |
|
||||
word-break: keep-all; |
|
||||
} |
|
||||
.query-result{ |
|
||||
word-break: break-all; |
|
||||
} |
|
||||
</style> |
|
||||
<div class="container" style="padding-top:70px;"> |
|
||||
<div class="col-xs-12 col-sm-10 col-md-8 center-block" style="float: none;"> |
|
||||
<div class="panel panel-primary"> |
|
||||
<div class="panel-heading"><h3 class="panel-title">后台管理首页</h3></div> |
|
||||
<div class="list-group"> |
|
||||
<div class="list-group-item"><span class="glyphicon glyphicon-stats"></span> <b>宝塔插件统计:</b>共有 {$stat.total} 个,其中免费插件 {$stat.free} 个,专业版插件 {$stat.pro} 个,企业版插件 {$stat.ltd} 个,第三方插件 {$stat.third} 个</div> |
|
||||
<div class="list-group-item"><span class="glyphicon glyphicon-tint"></span> <b>使用记录统计:</b>历史总共数量:{$stat.record_total},正在使用数量:{$stat.record_isuse}</div> |
|
||||
<div class="list-group-item"><span class="glyphicon glyphicon-time"></span> <b>任务运行情况:</b>上次运行时间:{$stat.runtime|raw} <a href="/admin/set/mod/task" class="btn btn-xs btn-info">查看详情</a></div> |
|
||||
<div class="list-group-item"><span class="glyphicon glyphicon-cog"></span> <b>常用功能入口:</b><a href="/admin/plugins" class="btn btn-xs btn-default">插件列表</a> <a href="/admin/record" class="btn btn-xs btn-default">使用记录</a> <a href="/admin/list" class="btn btn-xs btn-default">黑白名单</a> <a href="/download" class="btn btn-xs btn-default" target="_blank">安装脚本</a></div> |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="panel panel-info"> |
|
||||
<div class="panel-heading"> |
|
||||
<h3 class="panel-title">服务器信息</h3> |
|
||||
</div> |
|
||||
<table class="table table-bordered"> |
|
||||
<tbody> |
|
||||
<tr> |
|
||||
<td class="query-title">框架版本</td> |
|
||||
<td class="query-result">{$info.framework_version}</td> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td class="query-title">PHP版本</td> |
|
||||
<td class="query-result">{$info.php_version}</td> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td class="query-title">MySQL版本</td> |
|
||||
<td class="query-result">{$info.mysql_version}</td> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td class="query-title">WEB软件</td> |
|
||||
<td class="query-result">{$info.software}</td> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td class="query-title">操作系统</td> |
|
||||
<td class="query-result">{$info.os}</td> |
|
||||
</tr> |
|
||||
<tr> |
|
||||
<td class="query-title">服务器时间</td> |
|
||||
<td class="query-result">{$info.date}</td> |
|
||||
</tr> |
|
||||
</tbody> |
|
||||
</table> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
{extend name="admin/layout" /} |
||||
|
{block name="title"}宝塔第三方云端管理中心{/block} |
||||
|
{block name="main"} |
||||
|
<style> |
||||
|
.table>tbody>tr>td{white-space: normal;} |
||||
|
.query-title { |
||||
|
background-color:#f5fafe; |
||||
|
word-break: keep-all; |
||||
|
} |
||||
|
.query-result{ |
||||
|
word-break: break-all; |
||||
|
} |
||||
|
</style> |
||||
|
<div class="container" style="padding-top:70px;"> |
||||
|
<div class="col-xs-12 col-sm-10 col-md-8 center-block" style="float: none;"> |
||||
|
<div class="panel panel-primary"> |
||||
|
<div class="panel-heading"><h3 class="panel-title">后台管理首页</h3></div> |
||||
|
<div class="list-group"> |
||||
|
<div class="list-group-item"><span class="glyphicon glyphicon-stats"></span> <b>宝塔插件统计:</b>共有 {$stat.total} 个,其中免费插件 {$stat.free} 个,专业版插件 {$stat.pro} 个,企业版插件 {$stat.ltd} 个,第三方插件 {$stat.third} 个</div> |
||||
|
<div class="list-group-item"><span class="glyphicon glyphicon-tint"></span> <b>使用记录统计:</b>历史总共数量:{$stat.record_total},正在使用数量:{$stat.record_isuse}</div> |
||||
|
<div class="list-group-item"><span class="glyphicon glyphicon-time"></span> <b>任务运行情况:</b>上次运行时间:{$stat.runtime|raw} <a href="/admin/set/mod/task" class="btn btn-xs btn-info">查看详情</a></div> |
||||
|
<div class="list-group-item"><span class="glyphicon glyphicon-cog"></span> <b>常用功能入口:</b><a href="/admin/plugins" class="btn btn-xs btn-default">插件列表</a> <a href="/admin/record" class="btn btn-xs btn-default">使用记录</a> <a href="/admin/list" class="btn btn-xs btn-default">黑白名单</a> <a href="/download" class="btn btn-xs btn-default" target="_blank">安装脚本</a></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="panel panel-info"> |
||||
|
<div class="panel-heading"> |
||||
|
<h3 class="panel-title">服务器信息</h3> |
||||
|
</div> |
||||
|
<table class="table table-bordered"> |
||||
|
<tbody> |
||||
|
<tr> |
||||
|
<td class="query-title">框架版本</td> |
||||
|
<td class="query-result">{$info.framework_version}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td class="query-title">PHP版本</td> |
||||
|
<td class="query-result">{$info.php_version}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td class="query-title">MySQL版本</td> |
||||
|
<td class="query-result">{$info.mysql_version}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td class="query-title">WEB软件</td> |
||||
|
<td class="query-result">{$info.software}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td class="query-title">操作系统</td> |
||||
|
<td class="query-result">{$info.os}</td> |
||||
|
</tr> |
||||
|
<tr> |
||||
|
<td class="query-title">服务器时间</td> |
||||
|
<td class="query-result">{$info.date}</td> |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
{/block} |
{/block} |
@ -0,0 +1,86 @@ |
|||||
|
{extend name="admin/layout" /} |
||||
|
{block name="title"}自签名SSL证书生成{/block} |
||||
|
{block name="main"} |
||||
|
<style> |
||||
|
.control-label[is-required]:before { |
||||
|
content: "*"; |
||||
|
color: #f56c6c; |
||||
|
margin-right: 4px; |
||||
|
} |
||||
|
</style> |
||||
|
<div class="container" style="padding-top:70px;"> |
||||
|
<div class="col-sm-12 col-md-10 col-lg-8 center-block" style="float: none;"> |
||||
|
<div class="panel panel-primary"> |
||||
|
<div class="panel-heading"><h3 class="panel-title">自签名SSL证书生成</h3></div> |
||||
|
<div class="panel-body"> |
||||
|
{if $isca} |
||||
|
<div class="alert alert-warning" style="word-break:break-all;">下载CA证书并导入,可解决浏览器不安全提醒。<br/>Windows:<a href="/ssl/baota_root.pfx">baota_root.pfx</a>(密码为空),Mac/Linux:<a href="/ssl/baota_root.crt">baota_root.crt</a></div> |
||||
|
<form onsubmit="return makeSSL(this)" method="post" class="form" role="form"> |
||||
|
<div class="form-group"> |
||||
|
<label is-required="true" class="control-label">域名列表:</label> |
||||
|
<textarea class="form-control" name="domain_list" rows="6" placeholder="每行一个域名/IP,支持通配符" required></textarea> |
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<label class="control-label">通用名称:</label> |
||||
|
<input type="text" name="common_name" value="" placeholder="留空则为域名列表第一个域名" class="form-control"/> |
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<label is-required="true" class="control-label">有效天数:</label> |
||||
|
<input type="number" name="validity" value="3650" class="form-control" required/> |
||||
|
</div> |
||||
|
<div class="form-group text-center"> |
||||
|
<input type="submit" name="submit" value="生成自签名证书" class="btn btn-success btn-block"/> |
||||
|
</div> |
||||
|
<div class="form-group row" id="result" style="display:none;"> |
||||
|
<div class="col-md-6"> |
||||
|
<label class="control-label">SSL证书:</label> |
||||
|
<textarea class="form-control" name="ssl_cert" rows="5" onclick="copy(this)" title="点击复制"></textarea> |
||||
|
</div> |
||||
|
<div class="col-md-6"> |
||||
|
<label class="control-label">SSL证书私钥:</label> |
||||
|
<textarea class="form-control" name="ssl_key" rows="5" onclick="copy(this)" title="点击复制"></textarea> |
||||
|
</div> |
||||
|
</div> |
||||
|
</form> |
||||
|
{else} |
||||
|
<div class="alert alert-danger" role="alert">你还没有生成CA证书,无法生成SSL证书!</div> |
||||
|
<div class="alert alert-info" style="word-break:break-all;">执行以下命令,生成自签名CA证书。然后,可通过接口或当前页面生成SSL证书,用于面板访问。</div> |
||||
|
<div class="list-group-item" style="word-break:break-all;">cd {:app()->getRootPath()}app/script && chmod +x cacert.sh && ./cacert.sh</div><br/> |
||||
|
{/if} |
||||
|
</div> |
||||
|
</div> |
||||
|
<script src="{$cdnpublic}layer/3.5.1/layer.js"></script> |
||||
|
<script> |
||||
|
function makeSSL(obj){ |
||||
|
var ii = layer.load(2, {shade:[0.1,'#fff']}); |
||||
|
$.ajax({ |
||||
|
type : 'POST', |
||||
|
url : '/admin/ssl', |
||||
|
data : $(obj).serialize(), |
||||
|
dataType : 'json', |
||||
|
success : function(data) { |
||||
|
layer.close(ii); |
||||
|
if(data.code == 0){ |
||||
|
$("textarea[name='ssl_cert']").val(data.cert); |
||||
|
$("textarea[name='ssl_key']").val(data.key); |
||||
|
$("#result").show(); |
||||
|
layer.msg('SSL证书生成成功', {icon:1, time:800}); |
||||
|
}else{ |
||||
|
layer.alert(data.msg, {icon: 2}) |
||||
|
} |
||||
|
}, |
||||
|
error:function(data){ |
||||
|
layer.close(ii); |
||||
|
layer.msg('服务器错误'); |
||||
|
} |
||||
|
}); |
||||
|
return false; |
||||
|
} |
||||
|
function copy(obj){ |
||||
|
if($(obj).val() == '') return; |
||||
|
$(obj).select(); |
||||
|
document.execCommand("Copy"); |
||||
|
layer.msg('复制成功', {icon:1, time:500}); |
||||
|
} |
||||
|
</script> |
||||
|
{/block} |
@ -1,60 +1,60 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html> |
|
||||
<head> |
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
|
||||
<title>温馨提示</title> |
|
||||
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> |
|
||||
<meta name="renderer" content="webkit"/> |
|
||||
<style type="text/css"> |
|
||||
*{box-sizing:border-box;margin:0;padding:0;font-family:Lantinghei SC,Open Sans,Arial,Hiragino Sans GB,Microsoft YaHei,"微软雅黑",STHeiti,WenQuanYi Micro Hei,SimSun,sans-serif;-webkit-font-smoothing:antialiased} |
|
||||
body{padding:70px 0;background:#edf1f4;font-weight:400;font-size:1pc;-webkit-text-size-adjust:none;color:#333} |
|
||||
a{outline:0;color:#3498db;text-decoration:none;cursor:pointer} |
|
||||
.system-message{margin:20px 5%;padding:40px 20px;background:#fff;box-shadow:1px 1px 1px hsla(0,0%,39%,.1);text-align:center} |
|
||||
.system-message h1{margin:0;margin-bottom:9pt;color:#444;font-weight:400;font-size:40px} |
|
||||
.system-message .jump,.system-message .image{margin:20px 0;padding:0;padding:10px 0;font-weight:400} |
|
||||
.system-message .jump{font-size:14px} |
|
||||
.system-message .jump a{color:#333} |
|
||||
.system-message p{font-size:9pt;line-height:20px} |
|
||||
.system-message .btn{display:inline-block;margin-right:10px;width:138px;height:2pc;border:1px solid #44a0e8;border-radius:30px;color:#44a0e8;text-align:center;font-size:1pc;line-height:2pc;margin-bottom:5px;} |
|
||||
.success .btn{border-color:#69bf4e;color:#69bf4e} |
|
||||
.error .btn{border-color:#ff8992;color:#ff8992} |
|
||||
.info .btn{border-color:#3498db;color:#3498db} |
|
||||
.copyright p{width:100%;color:#919191;text-align:center;font-size:10px} |
|
||||
.system-message .btn-grey{border-color:#bbb;color:#bbb} |
|
||||
.clearfix:after{clear:both;display:block;visibility:hidden;height:0;content:"."} |
|
||||
@media (max-width:768px){body {padding:20px 0;}} |
|
||||
@media (max-width:480px){.system-message h1{font-size:30px;}} |
|
||||
</style> |
|
||||
</head> |
|
||||
<body> |
|
||||
<div class="system-message {$code}"> |
|
||||
<div class="image"> |
|
||||
<img src="/static/images/{$code}.svg" alt="" width="150" /> |
|
||||
</div> |
|
||||
<h1>{$msg}</h1> |
|
||||
{if $url} |
|
||||
<p class="jump"> |
|
||||
页面将在 <span id="wait">{$wait}</span> 秒后自动跳转 |
|
||||
</p> |
|
||||
{/if} |
|
||||
<p class="clearfix"> |
|
||||
<a href="javascript:history.go(-1);" class="btn btn-grey">返回上一页</a> |
|
||||
{if $url} |
|
||||
<a href="{$url}" class="btn btn-primary">立即跳转</a> |
|
||||
{/if} |
|
||||
</p> |
|
||||
</div> |
|
||||
<script type="text/javascript"> |
|
||||
(function () { |
|
||||
var wait = document.getElementById('wait'); |
|
||||
var interval = setInterval(function () { |
|
||||
var time = --wait.innerHTML; |
|
||||
if (time <= 0) { |
|
||||
location.href = "{$url}"; |
|
||||
clearInterval(interval); |
|
||||
} |
|
||||
}, 1000); |
|
||||
})(); |
|
||||
</script> |
|
||||
</body> |
|
||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<head> |
||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
||||
|
<title>温馨提示</title> |
||||
|
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> |
||||
|
<meta name="renderer" content="webkit"/> |
||||
|
<style type="text/css"> |
||||
|
*{box-sizing:border-box;margin:0;padding:0;font-family:Lantinghei SC,Open Sans,Arial,Hiragino Sans GB,Microsoft YaHei,"微软雅黑",STHeiti,WenQuanYi Micro Hei,SimSun,sans-serif;-webkit-font-smoothing:antialiased} |
||||
|
body{padding:70px 0;background:#edf1f4;font-weight:400;font-size:1pc;-webkit-text-size-adjust:none;color:#333} |
||||
|
a{outline:0;color:#3498db;text-decoration:none;cursor:pointer} |
||||
|
.system-message{margin:20px 5%;padding:40px 20px;background:#fff;box-shadow:1px 1px 1px hsla(0,0%,39%,.1);text-align:center} |
||||
|
.system-message h1{margin:0;margin-bottom:9pt;color:#444;font-weight:400;font-size:40px} |
||||
|
.system-message .jump,.system-message .image{margin:20px 0;padding:0;padding:10px 0;font-weight:400} |
||||
|
.system-message .jump{font-size:14px} |
||||
|
.system-message .jump a{color:#333} |
||||
|
.system-message p{font-size:9pt;line-height:20px} |
||||
|
.system-message .btn{display:inline-block;margin-right:10px;width:138px;height:2pc;border:1px solid #44a0e8;border-radius:30px;color:#44a0e8;text-align:center;font-size:1pc;line-height:2pc;margin-bottom:5px;} |
||||
|
.success .btn{border-color:#69bf4e;color:#69bf4e} |
||||
|
.error .btn{border-color:#ff8992;color:#ff8992} |
||||
|
.info .btn{border-color:#3498db;color:#3498db} |
||||
|
.copyright p{width:100%;color:#919191;text-align:center;font-size:10px} |
||||
|
.system-message .btn-grey{border-color:#bbb;color:#bbb} |
||||
|
.clearfix:after{clear:both;display:block;visibility:hidden;height:0;content:"."} |
||||
|
@media (max-width:768px){body {padding:20px 0;}} |
||||
|
@media (max-width:480px){.system-message h1{font-size:30px;}} |
||||
|
</style> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div class="system-message {$code}"> |
||||
|
<div class="image"> |
||||
|
<img src="/static/images/{$code}.svg" alt="" width="150" /> |
||||
|
</div> |
||||
|
<h1>{$msg}</h1> |
||||
|
{if $url} |
||||
|
<p class="jump"> |
||||
|
页面将在 <span id="wait">{$wait}</span> 秒后自动跳转 |
||||
|
</p> |
||||
|
{/if} |
||||
|
<p class="clearfix"> |
||||
|
<a href="javascript:history.go(-1);" class="btn btn-grey">返回上一页</a> |
||||
|
{if $url} |
||||
|
<a href="{$url}" class="btn btn-primary">立即跳转</a> |
||||
|
{/if} |
||||
|
</p> |
||||
|
</div> |
||||
|
<script type="text/javascript"> |
||||
|
(function () { |
||||
|
var wait = document.getElementById('wait'); |
||||
|
var interval = setInterval(function () { |
||||
|
var time = --wait.innerHTML; |
||||
|
if (time <= 0) { |
||||
|
location.href = "{$url}"; |
||||
|
clearInterval(interval); |
||||
|
} |
||||
|
}, 1000); |
||||
|
})(); |
||||
|
</script> |
||||
|
</body> |
||||
</html> |
</html> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue