From bcfdd2216138268a7cd54a86bebc28ed9a1e5f15 Mon Sep 17 00:00:00 2001
From: Mr Chen
Date: Wed, 6 Nov 2024 02:08:35 +0800
Subject: [PATCH] update
---
new_cli.sh | 8 ++-
panel_tools.py | 7 +-
web/admin/dashboard/login.py | 46 ++++++++++---
web/admin/setting/secondary_verifiy.py | 44 +++++++++----
web/admin/setup/option.py | 3 +
web/admin/site/__init__.py | 45 ++++++++++++-
web/core/db.py | 2 +
web/core/mw.py | 13 ++++
web/static/app/config.js | 4 +-
web/templates/default/login.html | 2 +-
web/templates/default/setting.html | 6 +-
web/thisdb/user.py | 15 +++--
web/utils/config.py | 4 ++
web/utils/site.py | 89 +++++++++++++++-----------
web/utils/system/main.py | 9 +--
15 files changed, 216 insertions(+), 81 deletions(-)
diff --git a/new_cli.sh b/new_cli.sh
index 4d6a96388..77c21ddf6 100755
--- a/new_cli.sh
+++ b/new_cli.sh
@@ -51,7 +51,7 @@ mw_start_debug(){
fi
python3 panel_task.py >> $DIR/logs/panel_task.log 2>&1 &
- port=7200
+ port=7200
if [ -f /www/server/mdserver-web/data/port.pl ];then
port=$(cat /www/server/mdserver-web/data/port.pl)
fi
@@ -64,7 +64,11 @@ mw_start_debug(){
}
mw_start_panel(){
- cd ${DIR}/web && gunicorn -b :7200 -w 1 app:app
+ port=7200
+ if [ -f ${DIR}/data/port.pl ];then
+ port=$(cat ${DIR}/data/port.pl)
+ fi
+ cd ${DIR}/web && gunicorn -b :${port} -w 1 app:app
}
mw_start_bgtask(){
diff --git a/panel_tools.py b/panel_tools.py
index 45af39793..cd2e3734f 100755
--- a/panel_tools.py
+++ b/panel_tools.py
@@ -158,9 +158,10 @@ def mwcli(mw_input=0):
open_ssh_port()
print("|-已开启!")
elif mw_input == 26:
- auth_secret = 'data/auth_secret.pl'
- if os.path.exists(auth_secret):
- os.remove(auth_secret)
+ two_step_verification = thisdb.getOptionByJson('two_step_verification', default={'open':False})
+ if two_step_verification['open']:
+ two_step_verification['open'] = False
+ thisdb.setOption('two_step_verification', json.dumps(two_step_verification))
print("|-关闭二次验证成功!")
else:
print("|-二次验证已关闭!")
diff --git a/web/admin/dashboard/login.py b/web/admin/dashboard/login.py
index 7f1abe8eb..746560ce2 100644
--- a/web/admin/dashboard/login.py
+++ b/web/admin/dashboard/login.py
@@ -20,8 +20,6 @@ from flask import request,g
from admin.common import isLogined
from admin.user_login_check import panel_login_required
from admin import cache,session
-from admin import model
-from admin.model import db,TempLogin,Users
import core.mw as mw
import thisdb
@@ -63,7 +61,7 @@ def login_temp_user(token):
stime = int(time.time())
- tmp_data = model.getTempLoginByToken(token)
+ tmp_data = thisdb.getTempLoginByToken(token)
if not tmp_data:
setErrorNum(skey)
return '验证失败!'
@@ -73,12 +71,10 @@ def login_temp_user(token):
return "过期"
user_data = thisdb.getUserById(1)
-
login_addr = mw.getClientIp() + ":" + str(request.environ.get('REMOTE_PORT'))
mw.writeLog('用户临时登录', "登录成功,帐号:{1},登录IP:{2}",(user_data['name'], login_addr))
- TempLogin.query.filter(TempLogin.id==tmp_data['id']).update({"login_time": stime, 'state': 1, 'login_addr': login_addr})
- db.session.commit()
+ mw.M('temp_login').where('id=?',(tmp_data['id'],)).update({"login_time": stime, 'state': 1, 'login_addr': login_addr})
session['login'] = True
session['username'] = user_data['name']
@@ -105,11 +101,11 @@ def login():
session['login'] = False
session['overdue'] = 0
- db_path = model.getOption('admin_path')
+ db_path = thisdb.getOption('admin_path')
if db_path == '':
return render_template('default/login.html')
else:
- unauthorized_status = model.getOption('unauthorized_status')
+ unauthorized_status = thisdb.getOption('unauthorized_status')
if unauthorized_status == '0':
return render_template('default/path.html')
return Response(status=int(unauthorized_status))
@@ -134,6 +130,32 @@ def check_login():
return mw.returnData(True,'已登录')
return mw.returnData(False,'未登录')
+@blueprint.route("/verify_login", methods=['POST'])
+def verifyLogin():
+ import pyotp
+
+ username = request.form.get('username', '').strip()
+ password = request.form.get('password', '').strip()
+ password = mw.md5(password)
+
+ info = thisdb.getUserByRoot()
+ if info['name'] != username or info['password'] != password:
+ return mw.returnJson(-1, "密码错误?")
+
+ auth = request.form.get('auth', '').strip()
+ two_step_verification = thisdb.getOptionByJson('two_step_verification', default={'open':False})
+ if two_step_verification['open']:
+ sec = mw.deDoubleCrypt('mdserver-web', two_step_verification['secret'])
+ totp = pyotp.TOTP(sec)
+ if totp.verify(auth):
+ session['login'] = True
+ session['username'] = info['name']
+ session['overdue'] = int(time.time()) + 7 * 24 * 60 * 60
+
+ thisdb.updateUserLoginTime()
+ return mw.returnData(1, '二次验证成功!')
+ return mw.returnData(-1, '二次验证失败!')
+
# 执行登录操作
@blueprint.route('/do_login', endpoint='do_login', methods=['POST'])
def do_login():
@@ -181,9 +203,15 @@ def do_login():
mw.writeLog('用户登录', mw.getInfo(msg))
return mw.returnData(-1, mw.getInfo("用户名或密码错误,您还可以尝试[{1}]次!", (str(login_cache_count - login_cache_limit))))
+ cache.delete('login_cache_limit')
+ # 二步验证密钥
+ two_step_verification = thisdb.getOptionByJson('two_step_verification', default={'open':False})
+ if two_step_verification['open']:
+ return mw.returnData(2, '需要两步验证!')
session['login'] = True
session['username'] = info['name']
session['overdue'] = int(time.time()) + 7 * 24 * 60 * 60
-
+
+ thisdb.updateUserLoginTime()
return mw.returnJson(1, '登录成功,正在跳转...')
diff --git a/web/admin/setting/secondary_verifiy.py b/web/admin/setting/secondary_verifiy.py
index 562383706..2e170bf56 100644
--- a/web/admin/setting/secondary_verifiy.py
+++ b/web/admin/setting/secondary_verifiy.py
@@ -25,30 +25,48 @@ import core.mw as mw
import utils.config as utils_config
from .setting import blueprint
+import thisdb
-
+# 获取二次验证信息
@blueprint.route('/get_auth_secret', endpoint='get_auth_secret', methods=['POST'])
@panel_login_required
def get_auth_secret():
- reset = request.form.get('reset', '')
- __file = mw.getCommonFile()
-
import pyotp
- auth = __file['auth_secret']
+
+ reset = request.form.get('reset', '')
tag = 'mdserver-web'
- if os.path.exists(auth) and reset != '1':
- content = mw.readFile(auth)
- sec = mw.deDoubleCrypt(tag,content)
+ two_step_verification = thisdb.getOptionByJson('two_step_verification', default={'open':False})
+
+ if 'secret' in two_step_verification and reset != '1':
+ secret = mw.deDoubleCrypt(tag, two_step_verification['secret'])
else:
- sec = pyotp.random_base32()
- crypt_data = mw.enDoubleCrypt(tag, sec)
- mw.writeFile(auth, crypt_data)
+ secret = pyotp.random_base32()
+ crypt_data = mw.enDoubleCrypt(tag, secret)
+ two_step_verification['secret'] = crypt_data
+ thisdb.setOption('two_step_verification', json.dumps(two_step_verification))
ip = mw.getHostAddr()
- url = pyotp.totp.TOTP(sec).provisioning_uri(name=ip, issuer_name=tag)
+ url = pyotp.totp.TOTP(secret).provisioning_uri(name=ip, issuer_name=tag)
rdata = {}
- rdata['secret'] = sec
+ rdata['secret'] = secret
rdata['url'] = url
return mw.returnData(True, '设置成功!', rdata)
+
+
+# 设置二次验证,加强安全登录
+@blueprint.route('/set_auth_secret', endpoint='set_auth_secret', methods=['POST'])
+@panel_login_required
+def set_auth_secret():
+ two_step_verification = thisdb.getOptionByJson('two_step_verification', default={'open':False})
+ if two_step_verification['open']:
+ two_step_verification['open'] = False
+ thisdb.setOption('two_step_verification', json.dumps(two_step_verification))
+ return mw.returnData(True, '关闭成功!', 0)
+ else:
+ two_step_verification['open'] = True
+ thisdb.setOption('two_step_verification', json.dumps(two_step_verification))
+ return mw.returnData(True, '开启成功!', 1)
+
+
\ No newline at end of file
diff --git a/web/admin/setup/option.py b/web/admin/setup/option.py
index da08bedd0..9a433961e 100644
--- a/web/admin/setup/option.py
+++ b/web/admin/setup/option.py
@@ -32,6 +32,9 @@ def init_option():
# basic auth 配置
thisdb.setOption('basic_auth', json.dumps({'open':False}))
+ # 二步验证|默认关闭
+ thisdb.setOption('two_step_verification', json.dumps({'open':False}))
+
# 开启后台任务
# model.setOption('run_bg_task', 'close')
diff --git a/web/admin/site/__init__.py b/web/admin/site/__init__.py
index 6036672f2..3bdf5979d 100644
--- a/web/admin/site/__init__.py
+++ b/web/admin/site/__init__.py
@@ -26,7 +26,7 @@ blueprint = Blueprint('site', __name__, url_prefix='/site', template_folder='../
def index():
return render_template('site.html')
-# 插件列表
+# 站点列表
@blueprint.route('/list', endpoint='list', methods=['GET','POST'])
@panel_login_required
def list():
@@ -42,11 +42,54 @@ def list():
data['page'] = mw.getPage({'count':info['count'],'tojs':'getWeb','p':p, 'row':limit})
return data
+#添加站点
+@blueprint.route('/add', endpoint='add',methods=['POST'])
+@panel_login_required
+def add():
+ webname = request.form.get('webinfo', '')
+ ps = request.form.get('ps', '')
+ path = request.form.get('path', '')
+ version = request.form.get('version', '')
+ port = request.form.get('port', '')
+ return []
+
+# 获取站点类型
@blueprint.route('/get_site_types', endpoint='get_site_types',methods=['POST'])
@panel_login_required
def get_site_types():
return []
+# 获取站点根目录
+@blueprint.route('/get_root_dir', endpoint='get_root_dir',methods=['POST'])
+@panel_login_required
+def get_root_dir():
+ data = {}
+ data['dir'] = mw.getWwwDir()
+ return data
+
+# 检查OpenResty安装/启动状态
+@blueprint.route('/check_web_status', endpoint='check_web_status',methods=['POST'])
+@panel_login_required
+def check_web_status():
+ '''
+ 创建站点检查web服务
+ '''
+ if not mw.isInstalledWeb():
+ return mw.returnJson(False, '请安装并启动OpenResty服务!')
+
+ # 这个快点
+ pid = mw.getServerDir() + '/openresty/nginx/logs/nginx.pid'
+ if not os.path.exists(pid):
+ return mw.returnData(False, '请启动OpenResty服务!')
+ return mw.returnData(True, 'OK')
+
+# 获取PHP版本
+@blueprint.route('/get_php_version', endpoint='get_php_version',methods=['POST'])
+@panel_login_required
+def get_php_version():
+ return site.getPhpVersion()
+
+
@blueprint.route('/get_cli_php_version', endpoint='get_cli_php_version',methods=['POST'])
@panel_login_required
def get_cli_php_version():
diff --git a/web/core/db.py b/web/core/db.py
index 27b97ae9e..6550f77c8 100755
--- a/web/core/db.py
+++ b/web/core/db.py
@@ -39,6 +39,8 @@ class Sql():
__OPT_FIELD = "*" # field条件
__OPT_PARAM = () # where值
+ __debug = False
+
def __init__(self):
self.__DB_FILE = getPanelDir()+'/data/panel.db'
diff --git a/web/core/mw.py b/web/core/mw.py
index 8ec077999..603456371 100644
--- a/web/core/mw.py
+++ b/web/core/mw.py
@@ -909,6 +909,19 @@ def panelCmd(method):
# ------------------------------ panel end -----------------------------
# ------------------------------ openresty start -----------------------------
+
+def checkWebConfig():
+ op_dir = getServerDir() + '/openresty/nginx'
+ # "ulimit -n 10240 && " +
+ cmd = op_dir + "/sbin/nginx -t -c " + op_dir + "/conf/nginx.conf"
+ result = execShell(cmd)
+ searchStr = 'test is successful'
+ if result[1].find(searchStr) == -1:
+ msg = getInfo('配置文件错误: {1}', (result[1],))
+ writeLog("软件管理", msg)
+ return result[1]
+ return True
+
def restartWeb():
return opWeb("reload")
diff --git a/web/static/app/config.js b/web/static/app/config.js
index 066a16dbe..542437619 100755
--- a/web/static/app/config.js
+++ b/web/static/app/config.js
@@ -1236,13 +1236,13 @@ function setTempAccess(){
});
}
-//二次验证
+//二步验证
function setAuthBind(){
$.post('/setting/get_auth_secret', {}, function(rdata){
console.log(rdata);
var tip = layer.open({
area: ['500px', '355px'],
- title: '二次验证设置',
+ title: '二步验证设置',
closeBtn:1,
shift: 0,
type: 1,
diff --git a/web/templates/default/login.html b/web/templates/default/login.html
index fb471f309..c361e6c3c 100755
--- a/web/templates/default/login.html
+++ b/web/templates/default/login.html
@@ -231,7 +231,7 @@ $('#login-button').click(function(){
layer.prompt({
formType: 3,
value: '',
- title: '二次验证',
+ title: '二步验证',
}, function(value, index, elem){
$.post('/verify_login',{'auth':value,'username':username,'password':password},function(vdata){
if (vdata.status < 0){
diff --git a/web/templates/default/setting.html b/web/templates/default/setting.html
index c001f7375..588d1eeb0 100755
--- a/web/templates/default/setting.html
+++ b/web/templates/default/setting.html
@@ -149,11 +149,11 @@
- 二次验证
-
+ 二步验证
+
- 二次验证,加强安全登录
+ 二步验证,加强安全登录
diff --git a/web/thisdb/user.py b/web/thisdb/user.py
index 519a3476c..ac94b222b 100644
--- a/web/thisdb/user.py
+++ b/web/thisdb/user.py
@@ -10,9 +10,11 @@
import core.mw as mw
+__field = 'id,name,password,login_ip,login_time,phone,email,add_time,update_time'
+
# 初始化用户信息
def initAdminUser():
- data = mw.M('users').field('id').where('id=?', (1,)).find()
+ data = mw.M('users').field(__field).where('id=?', (1,)).find()
if data is None:
name = mw.getRandomString(8).lower()
password = mw.getRandomString(8).lower()
@@ -39,8 +41,7 @@ def getUserByName(name,
'''
获取用户信息通过用户名
'''
- users_field = 'id,name,password,login_ip,login_time,phone,email,add_time,update_time'
- data = mw.M('users').field(users_field).where('name=?', (name,)).find()
+ data = mw.M('users').field(__field).where('name=?', (name,)).find()
if data is None:
return None
row = {}
@@ -60,8 +61,7 @@ def getUserById(id,
'''
获取用户信息通过用户名
'''
- users_field = 'id,name,password,login_ip,login_time,phone,email,add_time,update_time'
- data = mw.M('users').field(users_field).where('id=?', (1,)).find()
+ data = mw.M('users').field(__field).where('id=?', (1,)).find()
if data is None:
return None
row = {}
@@ -83,6 +83,11 @@ def getUserByRoot() -> None:
'''
return getUserById(1)
+def updateUserLoginTime():
+ now_time = mw.formatDate()
+ mw.M('users').field(__field).where('id=?', (1,)).update({'login_time',now_time})
+ return True
+
def setUserByRoot(
name: str | None = None,
password: str | None = None,
diff --git a/web/utils/config.py b/web/utils/config.py
index 878dc74d3..89ffabb85 100644
--- a/web/utils/config.py
+++ b/web/utils/config.py
@@ -62,10 +62,14 @@ def getGlobalVar():
else:
data['ipv6'] = ''
+ # 获取ROOT用户名
+ data['username'] = mw.M('users').where("id=?", (1,)).getField('name')
+
# 获取未认证状态信息
unauthorized_status = thisdb.getOption('unauthorized_status', default='0')
data['unauthorized_status'] = getUnauthStatus(code=unauthorized_status)
data['basic_auth'] = thisdb.getOptionByJson('basic_auth', default={'open':False})
+ data['two_step_verification'] = thisdb.getOptionByJson('two_step_verification', default={'open':False})
# 服务器时间
sformat = 'date +"%Y-%m-%d %H:%M:%S %Z %z"'
diff --git a/web/utils/site.py b/web/utils/site.py
index a9a5b0c24..0d76ec0ff 100644
--- a/web/utils/site.py
+++ b/web/utils/site.py
@@ -18,43 +18,56 @@ from admin import model
import core.mw as mw
-def getPhpVersion():
- phpVersions = ('00', '52', '53', '54', '55',
- '56', '70', '71', '72', '73',
- '74', '80', '81', '82', '83',
- '84')
- data = []
- for val in phpVersions:
- tmp = {}
- if val == '00':
- tmp['version'] = '00'
- tmp['name'] = '纯静态'
- data.append(tmp)
- # 标准判断
- checkPath = mw.getServerDir() + '/php/' + val + '/bin/php'
- if os.path.exists(checkPath):
- tmp['version'] = val
- tmp['name'] = 'PHP-' + val
- data.append(tmp)
+class sites(object):
+ # lock
+ _instance_lock = threading.Lock()
+
+ @classmethod
+ def instance(cls, *args, **kwargs):
+ if not hasattr(sites, "_instance"):
+ with sites._instance_lock:
+ if not hasattr(sites, "_instance"):
+ sites._instance = sites(*args, **kwargs)
+ return sites._instance
+
+
+ def getPhpVersion(self):
+ phpVersions = ('00', '52', '53', '54', '55',
+ '56', '70', '71', '72', '73',
+ '74', '80', '81', '82', '83',
+ '84')
+ data = []
+ for val in phpVersions:
+ tmp = {}
+ if val == '00':
+ tmp['version'] = '00'
+ tmp['name'] = '纯静态'
+ data.append(tmp)
- # 其他PHP安装类型
- conf_dir = mw.getServerDir() + "/web_conf/php/conf"
- conf_list = os.listdir(conf_dir)
- l = len(conf_list)
- rep = r"enable-php-(.*?)\.conf"
- for name in conf_list:
- tmp = {}
- try:
- matchVer = re.search(rep, name).groups()[0]
- except Exception as e:
- continue
-
- if matchVer in phpVersions:
- continue
-
- tmp['version'] = matchVer
- tmp['name'] = 'PHP-' + matchVer
- data.append(tmp)
-
- return data
\ No newline at end of file
+ # 标准判断
+ checkPath = mw.getServerDir() + '/php/' + val + '/bin/php'
+ if os.path.exists(checkPath):
+ tmp['version'] = val
+ tmp['name'] = 'PHP-' + val
+ data.append(tmp)
+
+ # 其他PHP安装类型
+ conf_dir = mw.getServerDir() + "/web_conf/php/conf"
+ conf_list = os.listdir(conf_dir)
+ l = len(conf_list)
+ rep = r"enable-php-(.*?)\.conf"
+ for name in conf_list:
+ tmp = {}
+ try:
+ matchVer = re.search(rep, name).groups()[0]
+ except Exception as e:
+ continue
+
+ if matchVer in phpVersions:
+ continue
+
+ tmp['version'] = matchVer
+ tmp['name'] = 'PHP-' + matchVer
+ data.append(tmp)
+ return data
\ No newline at end of file
diff --git a/web/utils/system/main.py b/web/utils/system/main.py
index f2a29203b..8ace24d77 100644
--- a/web/utils/system/main.py
+++ b/web/utils/system/main.py
@@ -105,12 +105,13 @@ def getSystemVersion():
def getBootTime():
# 取系统启动时间
- uptime = mw.readFile('/proc/uptime')
- if uptime == False:
+ if os.path.exists('/proc/uptime'):
+ uptime = mw.readFile('/proc/uptime')
+ run_time = uptime.split()[0]
+ else:
start_time = psutil.boot_time()
run_time = time.time() - start_time
- else:
- run_time = uptime.split()[0]
+
tStr = float(run_time)
min = tStr / 60
hours = min / 60