114 lines
3.6 KiB
Python
114 lines
3.6 KiB
Python
import datetime
|
|
import hashlib
|
|
from functools import wraps
|
|
|
|
from pmc import DnfsComm
|
|
from dnfs import UsersTable, DnfsTable
|
|
|
|
import jwt
|
|
from flask import Blueprint, render_template, request, redirect, url_for, current_app, make_response, jsonify
|
|
|
|
login_bp = Blueprint('login', __name__, template_folder='templates/login')
|
|
|
|
|
|
comm = DnfsComm("http://localhost:8006")
|
|
|
|
|
|
def get_user_from_token():
|
|
token = request.cookies.get('token')
|
|
if not token:
|
|
return None
|
|
try:
|
|
payload = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=['HS256'])
|
|
return payload # 包含 user、user_id、exp 等字段
|
|
except jwt.ExpiredSignatureError:
|
|
return None
|
|
except jwt.InvalidTokenError:
|
|
return None
|
|
|
|
|
|
@login_bp.after_request
|
|
def add_cors_headers(response):
|
|
response.headers['Access-Control-Allow-Origin'] = '*' # 允许所有来源跨域访问,如需限制可替换为具体域名
|
|
response.headers['Access-Control-Allow-Headers'] = 'Content-Type,Authorization'
|
|
response.headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,DELETE,OPTIONS'
|
|
return response
|
|
|
|
|
|
def token_required(f):
|
|
@wraps(f)
|
|
def decorated(*args, **kwargs):
|
|
# 从cookie中获取token
|
|
token = request.cookies.get('token')
|
|
if not token:
|
|
return redirect(url_for('login.index'))
|
|
try:
|
|
jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=['HS256'])
|
|
except jwt.ExpiredSignatureError:
|
|
return redirect(url_for('login.index'))
|
|
except jwt.InvalidTokenError:
|
|
return redirect(url_for('login.index'))
|
|
return f(*args, **kwargs)
|
|
return decorated
|
|
|
|
|
|
@login_bp.route('/')
|
|
def index():
|
|
return render_template('index.html')
|
|
|
|
|
|
@login_bp.route('/api/login', methods=['GET', 'POST'])
|
|
def login():
|
|
if request.method == 'POST':
|
|
username = request.form.get('user-name')
|
|
password = request.form.get('user-passwd')
|
|
password = password.encode("utf-8")
|
|
hashed_password = hashlib.sha256(password).hexdigest()
|
|
try:
|
|
data = comm.get_and_trans(0)
|
|
dnfs_tab = DnfsTable(data)
|
|
users = dnfs_tab.query_by_title('Users')
|
|
table = UsersTable(users.content)
|
|
data = table.user_exists(username, hashed_password)
|
|
if not data:
|
|
return "用户登录失败", 401
|
|
_user_id, _username, _password, _role = data
|
|
except DnfsComm.GetFailed:
|
|
return "获取数据失败", 500
|
|
except DnfsTable.NotFound:
|
|
return "未找到用户表", 404
|
|
except UsersTable.NotFound:
|
|
return "用户不存在", 401
|
|
except Exception as e:
|
|
return str(e), 404
|
|
# 生成 Token
|
|
token = jwt.encode({
|
|
'user_id': _user_id,
|
|
'username': _username,
|
|
'role': _role,
|
|
'exp': datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=3)
|
|
}, current_app.config['SECRET_KEY'], algorithm='HS256')
|
|
|
|
# 构造 JSON 响应体
|
|
response = make_response(jsonify({
|
|
"redirect": url_for('login.mgmt'), # 跳转路径
|
|
"token": token
|
|
}))
|
|
|
|
# 设置 Cookie
|
|
response.set_cookie('token', token)
|
|
return response
|
|
else:
|
|
return "登录失败"
|
|
|
|
|
|
@login_bp.route('/api/mgmt')
|
|
@token_required
|
|
def mgmt():
|
|
payload = get_user_from_token()
|
|
if not payload:
|
|
return redirect(url_for('login.index'))
|
|
username = payload.get('username')
|
|
role = payload.get('role')
|
|
return render_template('mgmt.html', username=username, role=role)
|