pull/628/head
Mr Chen 6 months ago
parent ebf474aefb
commit 11f42d5d2c
  1. 70
      web/admin/dashboard/__init__.py
  2. 14
      web/admin/firewall/__init__.py
  3. 4
      web/admin/model/__init__.py
  4. 44
      web/admin/model/temp_login.py
  5. 30
      web/admin/model/user.py
  6. 3
      web/admin/setting/__init__.py
  7. 6
      web/admin/setting/main.py
  8. 54
      web/admin/setting/secondary_verifiy.py
  9. 62
      web/admin/setting/temp_login.py
  10. 60
      web/admin/setting/timezone.py
  11. 1
      web/admin/system/__init__.py
  12. 37
      web/core/mw.py
  13. 7
      web/static/app/config.js
  14. 19
      web/utils/firewall.py
  15. 8
      web/utils/mwplugin.py

@ -13,6 +13,7 @@ import time
from flask import Blueprint, render_template
from flask import make_response
from flask import redirect
from flask import Response
from flask import request,g
@ -20,6 +21,8 @@ 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
@ -77,9 +80,76 @@ def admin_safe_path(path):
# 定义登录入口相关方法
# ---------------------------------------------------------------------------------
def getErrorNum(key, limit=None):
key = mw.md5(key)
num = cache.get(key)
if not num:
num = 0
if not limit:
return num
if limit > num:
return True
return False
def setErrorNum(key, empty=False, expire=3600):
key = mw.md5(key)
num = cache.get(key)
if not num:
num = 0
else:
if empty:
cache.delete(key)
return True
cache.set(key, num + 1, expire)
return True
def login_temp_user(token):
if len(token) != 32:
return '错误的参数!'
skey = mw.getClientIp() + '_temp_login'
if not getErrorNum(skey, 10):
return '连续10次验证失败,禁止1小时'
stime = int(time.time())
tmp_data = model.getTempLoginByToken(token)
if not tmp_data:
setErrorNum(skey)
return '验证失败!'
if stime > int(tmp_data['expire']):
setErrorNum(skey)
return "过期"
user_data = model.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()
session['login'] = True
session['username'] = user_data['name']
session['tmp_login'] = True
session['tmp_login_id'] = str(tmp_data['id'])
session['tmp_login_expire'] = int(tmp_data['expire'])
session['uid'] = user_data['id']
return redirect('/')
# 登录页: 当设置了安全路径,本页失效。
@blueprint.route('/login')
def login():
# 临时登录功能
token = request.args.get('tmp_token', '').strip()
if token != '':
return login_temp_user(token)
# 注销登录
signout = request.args.get('signout', '')
if signout == 'True':
session.clear()

@ -50,7 +50,7 @@ def get_list():
data = {}
data['data'] = rows
data['page'] = mw.getPage({'count':count,'tojs':'getLogs','p':p})
data['page'] = mw.getPage({'count':count,'tojs':'getLogs','p':p,'row':limit})
return data
# 获取站点日志目录
@ -60,7 +60,7 @@ def get_www_path():
path = mw.getLogsDir()
return {'path': path}
# 获取站点日志目录
# 获取ssh信息
@blueprint.route('/get_ssh_info', endpoint='get_ssh_info', methods=['POST'])
@panel_login_required
def get_ssh_info():
@ -68,6 +68,16 @@ def get_ssh_info():
return mf.getSshInfo()
# 切换ping开关
@blueprint.route('/set_ping', endpoint='set_ping', methods=['POST'])
@panel_login_required
def set_ping():
mf = MwFirewall.instance()
return mf.setPing()

@ -21,5 +21,7 @@ from .task import addTask
from .task import getTaskCount,getTaskUnexecutedCount,getTaskList,getTaskFirstByRun
from .task import setTaskStatus,setTaskData
from .user import getUserByName,isLoginCheck
from .user import getUserByName,getUserById,isLoginCheck
from .temp_login import getTempLoginByToken,clearTempLogin

@ -0,0 +1,44 @@
# coding:utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
import time
from admin.model import db, TempLogin
import core.mw as mw
def getTempLoginByToken(token,
) -> None:
'''
获取用户信息通过用户名
'''
item = TempLogin.query.filter(TempLogin.token==token).first()
if item is None:
return None
row = {}
row['id'] = item.id
row['token'] = item.token
row['salt'] = item.salt
row['state'] = item.state
row['login_time'] = item.login_time
row['login_addr'] = item.login_addr
row['logout_time'] = item.logout_time
row['expire'] = item.expire
row['add_time'] = item.add_time
return row
def clearTempLogin()->bool:
'''
清空过期数据
'''
now_time = int(time.time())
TempLogin.query.filter(TempLogin.expire<now_time).delete()
db.session.commit()
return True

@ -40,3 +40,33 @@ def isLoginCheck(username, password) -> bool:
if info['password'] == mw.md5(password):
return True
return False
def getUserById(id,
) -> None:
'''
获取用户信息通过用户名
'''
item = Users.query.filter(Users.id==id).first()
if item is None:
return None
row = {}
row['id'] = item.id
row['name'] = item.name
row['password'] = item.password
row['login_ip'] = item.login_ip
row['login_time'] = item.login_time
row['phone'] = item.phone
row['email'] = item.email
row['add_time'] = item.add_time
row['update_time'] = item.update_time
return row
def isLoginCheck(username, password) -> bool:
info = getUserByName(data['username'])
if info is None:
return False
if info['password'] == mw.md5(password):
return True
return False

@ -10,6 +10,9 @@
from .main import *
from .temp_login import *
from .timezone import *
from .secondary_verifiy import *

@ -142,7 +142,7 @@ def set_basic_auth():
return mw.returnData(True, '设置成功!')
# 默认站点目录
# 设置站点状态
@blueprint.route('/set_status_code', endpoint='set_status_code', methods=['POST'])
@panel_login_required
def set_status_code():
@ -159,9 +159,7 @@ def set_status_code():
model.setOption('unauthorized_status', str(status_code))
mw.writeLog('面板设置', '将未授权响应状态码设置为:{0}:{1}'.format(status_code,info['text']))
return mw.returnData(True, '设置成功!')

@ -0,0 +1,54 @@
# coding:utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
import re
import json
import os
import time
from flask import Blueprint, render_template
from flask import request
from admin import model
from admin import session
from admin.model import db,TempLogin
from admin.user_login_check import panel_login_required
import core.mw as mw
import utils.config as utils_config
from .main import blueprint
@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']
tag = 'mdserver-web'
if os.path.exists(auth) and reset != '1':
content = mw.readFile(auth)
sec = mw.deDoubleCrypt(tag,content)
else:
sec = pyotp.random_base32()
crypt_data = mw.enDoubleCrypt(tag, sec)
mw.writeFile(auth, crypt_data)
ip = mw.getHostAddr()
url = pyotp.totp.TOTP(sec).provisioning_uri(name=ip, issuer_name=tag)
rdata = {}
rdata['secret'] = sec
rdata['url'] = url
return mw.returnData(True, '设置成功!', rdata)

@ -17,6 +17,7 @@ from flask import Blueprint, render_template
from flask import request
from admin import model
from admin import session
from admin.model import db,TempLogin
from admin.user_login_check import panel_login_required
@ -26,14 +27,40 @@ import utils.config as utils_config
from .main import blueprint
@blueprint.route('/get_temp_login', endpoint='get_temp_login', methods=['POST'])
@panel_login_required
def get_temp_login():
limit = request.form.get('limit', '5').strip()
p = request.form.get('page', '1').strip()
tojs = request.form.get('tojs', '').strip()
count = TempLogin.query.filter_by().count()
pagination = TempLogin.query.filter_by().order_by(TempLogin.expire.desc()).paginate(page=int(p), per_page=int(limit))
rows = []
for item in pagination.items:
t = {}
t['id'] = item.id
t['salt'] = item.salt
t['state'] = item.state
t['expire'] = item.expire
t['login_time'] = item.login_time
t['login_addr'] = item.login_addr
t['add_time'] = item.add_time
rows.append(t)
data = {}
data['data'] = rows
data['page'] = mw.getPage({'count':count,'tojs':'setTempAccessReq','p':p,'row':limit})
return data
@blueprint.route('/set_temp_login', endpoint='set_temp_login', methods=['POST'])
@panel_login_required
def set_temp_login():
# if 'tmp_login_expire' in session:
# return mw.returnData(False, '没有权限')
start_time = int(time.time())
# mw.M('temp_login').where(
# 'state=? and expire>?', (0, start_time)).delete()
model.clearTempLogin()
token = mw.getRandomString(48)
@ -52,14 +79,33 @@ def set_temp_login():
r = db.session.add(add_tl)
db.session.commit()
if r is None:
mw.writeLog('面板设置', '生成临时连接,过期时间:{}'.format(mw.formatDate(times=expire)))
return {'status': True, 'msg': "临时连接已生成", 'token': make_token, 'expire': expire}
return mw.returnData(False, '连接生成失败')
# if not mw.M('temp_login').count():
# pdata['id'] = 101
@blueprint.route('/remove_temp_login', endpoint='remove_temp_login', methods=['POST'])
@panel_login_required
def remove_temp_login():
tl_id = request.form.get('id', '10').strip()
# if mw.M('temp_login').insert(pdata):
# mw.writeLog('面板设置', '生成临时连接,过期时间:{}'.format(mw.formatDate(times=pdata['expire'])))
# return mw.getJson({'status': True, 'msg': "临时连接已生成", 'token': token, 'expire': pdata['expire']})
return mw.returnData(False, '连接生成失败')
r = TempLogin.query.filter(TempLogin.id == tl_id).delete()
db.session.commit()
if r > 0:
mw.writeLog('面板设置', '删除临时登录连接')
return mw.returnData(True, '删除成功')
return mw.returnData(False, '删除失败')
@blueprint.route('/get_temp_login_logs', endpoint='get_temp_login_logs', methods=['POST'])
@panel_login_required
def get_temp_login_logs():
if 'tmp_login_expire' in session:
return mw.returnData(False, '没有权限')
return mw.returnData(False, 'ok', [])

@ -0,0 +1,60 @@
# coding:utf-8
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
import re
import json
import os
from flask import Blueprint, render_template
from flask import request
from admin import model
from admin.user_login_check import panel_login_required
import core.mw as mw
import utils.config as utils_config
from .main import blueprint
# 时区相关
@blueprint.route('/get_timezone_list', endpoint='get_timezone_list', methods=['POST'])
@panel_login_required
def get_timezone_list():
import pytz
# 获取时区列表
# pytz.all_timezones | 所有
# pytz.common_timezones
return pytz.all_timezones
@blueprint.route('/sync_date', endpoint='sync_date', methods=['POST'])
@panel_login_required
def sync_date():
if mw.isAppleSystem():
return mw.returnData(True, '开发系统不必同步时间!')
data = mw.execShell('ntpdate -s time.nist.gov')
if data[0] == '':
return mw.returnData(True, '同步成功!')
return mw.returnData(False, '同步失败:' + data[0])
@blueprint.route('/set_timezone', endpoint='set_timezone', methods=['POST'])
@panel_login_required
def set_timezone():
# 设置时区列表
timezone = request.form.get('timezone', '').strip()
cmd = 'timedatectl set-timezone "'+timezone+'"'
mw.execShell(cmd)
return mw.returnData(True, '设置成功!')

@ -123,6 +123,7 @@ def set_control():
if _day < 1:
return mw.returnData(False, "设置失败!")
option.setOption('monitor_day', day, type='monitor')
return mw.returnData(True, "设置成功!")
elif stype == '2':
option.setOption('monitor_only_netio', 'close', type='monitor')
return mw.returnData(True, "设置成功!")

@ -576,6 +576,43 @@ def M(table):
sql = db.Sql()
return sql.table(table)
def enDoubleCrypt(key, strings):
# 加密字符串
try:
import base64
_key = md5(key).encode('utf-8')
_key = base64.urlsafe_b64encode(_key)
if type(strings) != bytes:
strings = strings.encode('utf-8')
import cryptography
from cryptography.fernet import Fernet
f = Fernet(_key)
result = f.encrypt(strings)
return result.decode('utf-8')
except:
writeFileLog(getTracebackInfo())
return strings
def deDoubleCrypt(key, strings):
# 解密字符串
try:
import base64
_key = md5(key).encode('utf-8')
_key = base64.urlsafe_b64encode(_key)
if type(strings) != bytes:
strings = strings.encode('utf-8')
from cryptography.fernet import Fernet
f = Fernet(_key)
result = f.decrypt(strings).decode('utf-8')
return result
except:
writeFileLog(getTracebackInfo())
return strings
# ------------------------------ openresty start -----------------------------
def restartWeb():

@ -452,7 +452,7 @@ function setTimezone(){
</div>",
success:function(){
var tbody = '';
$.post('/config/get_timezone_list', {}, function (rdata) {
$.post('/setting/get_timezone_list', {}, function (rdata) {
for (var i = 0; i < rdata.length; i++) {
if (rdata[i] == 'Asia/Shanghai'){
@ -1060,6 +1060,7 @@ function setTempAccessReq(page){
}
$.post('/setting/get_temp_login', {page:page}, function(rdata){
console.log(rdata);
if ( typeof(rdata.status) !='undefined' && !rdata.status){
showMsg(rdata.msg,function(){
layer.closeAll();
@ -1165,7 +1166,7 @@ function setStatusCode(o){
function setTempAccess(){
layer.open({
area: ['700px', '250px'],
area: ['700px', '380px'],
title: '临时授权管理',
closeBtn:1,
shift: 0,
@ -1268,7 +1269,7 @@ function setAuthBind(){
$('.reset_secret').click(function(){
layer.confirm('您确定要重置当前密钥吗?<br/><span style="color: red; ">重置密钥后,已关联密钥产品,将失效,请重新添加新密钥至产品。</span>',{title:'重置密钥',closeBtn:2,icon:13,cancel:function(){
}}, function() {
$.post('/config/get_auth_secret', {'reset':"1"},function(rdata){
$.post('/setting/get_auth_secret', {'reset':"1"},function(rdata){
showMsg("接口密钥已生成,重置密钥后,已关联密钥产品,将失效,请重新添加新密钥至产品。", function(){
$('input[name="secret"]').val(rdata.data['secret']);
$('.qrcode').html('').qrcode({ text: rdata.data['url']});

@ -117,4 +117,21 @@ class Firewall(object):
data['firewall_status'] = False
else:
data['firewall_status'] = self.getFwStatus()
return mw.getJson(data)
return mw.getJson(data)
def setPing(self):
if mw.isAppleSystem():
return mw.returnData(True, '开发机不能操作!')
status = request.form.get('status')
filename = '/etc/sysctl.conf'
conf = mw.readFile(filename)
if conf.find('net.ipv4.icmp_echo') != -1:
rep = r"net\.ipv4\.icmp_echo.*"
conf = re.sub(rep, 'net.ipv4.icmp_echo_ignore_all=' + status, conf)
else:
conf += "\nnet.ipv4.icmp_echo_ignore_all=" + status
mw.writeFile(filename, conf)
mw.execShell('sysctl -p')
return mw.returnData(True, '设置成功!')

@ -549,13 +549,7 @@ class MwPlugin(object):
data = self.getAllPluginList(type,keyword, page, size)
rdata['data'] = data[0]
args = {}
args['count'] = data[1]
args['p'] = page
args['tojs'] = 'getSList'
args['row'] = size
rdata['list'] = mw.getPage(args)
rdata['list'] = mw.getPage({'count':data[1],'p':page,'tojs':'getSList','row':size})
return rdata
# shell/bash方式调用

Loading…
Cancel
Save