mirror of https://github.com/flucont/btcloud.git
2 Commits
57cbf9315c
...
aba885f434
Author | SHA1 | Message | Date |
---|---|---|---|
flucout | aba885f434 |
update
|
3 months ago |
flucout | 5e1f19de53 |
支持生成自签SSL证书
|
3 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} |
@ -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> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue