feature: 登录&权限拦截

This commit is contained in:
zhengxinonly
2023-10-01 23:42:59 +08:00
parent 8765b2c344
commit 69a4955ce2
6 changed files with 86 additions and 46 deletions
+4
View File
@@ -1,4 +1,5 @@
import os import os
from datetime import timedelta
class BaseConfig: class BaseConfig:
@@ -8,6 +9,9 @@ class BaseConfig:
ROOT_PATH = os.path.dirname(os.path.abspath(__file__)) ROOT_PATH = os.path.dirname(os.path.abspath(__file__))
JWT_TOKEN_LOCATION = ["headers", "cookies"]
JWT_ACCESS_TOKEN_EXPIRES = timedelta(days=7)
class DevelopmentConfig(BaseConfig): class DevelopmentConfig(BaseConfig):
"""开发配置""" """开发配置"""
+42 -2
View File
@@ -1,8 +1,48 @@
from flask import Blueprint from flask import Blueprint, make_response, redirect, request
from flask_jwt_extended import (
create_access_token,
create_refresh_token,
jwt_required,
set_access_cookies,
set_refresh_cookies,
unset_access_cookies,
unset_refresh_cookies,
)
from pear_admin.extensions import db
from pear_admin.orms import UserORM
passport_api = Blueprint("passport", __name__) passport_api = Blueprint("passport", __name__)
@passport_api.post("/login") @passport_api.post("/login")
def login_in(): def login_in():
return {"message": "登录成功", "code": 0} data = request.get_json()
user: UserORM = db.session.execute(
db.select(UserORM).where(UserORM.username == data["username"])
).scalar()
if not user:
return {"message": "用户不存在", "code": -1}, 401
if user.check_password(data["password"]):
return {"message": "用户密码错误", "code": -1}, 401
access_token = create_access_token(user)
refresh_token = create_refresh_token(user)
response = make_response({"code": 0, "message": "登录成功"})
set_access_cookies(response, access_token)
set_refresh_cookies(response, refresh_token)
return response
@passport_api.route("/logout", methods=["GET", "POST"])
@jwt_required()
def logout():
response = make_response(redirect("/login"))
unset_access_cookies(response)
unset_refresh_cookies(response)
return response
+11
View File
@@ -1,3 +1,4 @@
from flask import redirect
from flask_jwt_extended import JWTManager from flask_jwt_extended import JWTManager
from pear_admin.orms.user import UserORM from pear_admin.orms.user import UserORM
@@ -14,3 +15,13 @@ def user_identity_lookup(user):
def user_lookup_callback(_jwt_header, jwt_data): def user_lookup_callback(_jwt_header, jwt_data):
identity = jwt_data["sub"] identity = jwt_data["sub"]
return UserORM.query.filter_by(id=identity).one_or_none() return UserORM.query.filter_by(id=identity).one_or_none()
@jwt.expired_token_loader
def expired_token_callback():
return redirect("/login")
@jwt.unauthorized_loader
def missing_token_callback(error):
return redirect("/login")
+3
View File
@@ -1,14 +1,17 @@
from flask import Blueprint, render_template from flask import Blueprint, render_template
from flask_jwt_extended import jwt_required
index_bp = Blueprint("index", __name__) index_bp = Blueprint("index", __name__)
@index_bp.route("/") @index_bp.route("/")
@jwt_required()
def index(): def index():
return render_template("index.html") return render_template("index.html")
@index_bp.route("/login.html") @index_bp.route("/login.html")
@index_bp.route("/login")
def login(): def login():
return render_template("login.html") return render_template("login.html")
+1 -1
View File
@@ -118,7 +118,7 @@
admin.logout(function () { admin.logout(function () {
popup.success("注销成功", function () { popup.success("注销成功", function () {
location.href = "./login.html"; location.href = "/api/v1/logout";
}); });
// 清空 tabs 缓存 // 清空 tabs 缓存
+24 -42
View File
@@ -22,7 +22,7 @@
<input <input
type="text" type="text"
name="username" name="username"
value="" value="正心全栈编程"
lay-verify="required" lay-verify="required"
placeholder="用户名" placeholder="用户名"
lay-reqtext="请填写用户名" lay-reqtext="请填写用户名"
@@ -40,7 +40,7 @@
<input <input
type="password" type="password"
name="password" name="password"
value="" value="123654"
lay-verify="required" lay-verify="required"
placeholder="密 码" placeholder="密 码"
lay-reqtext="请填写密码" lay-reqtext="请填写密码"
@@ -50,50 +50,21 @@
/> />
</div> </div>
</div> </div>
<div class="layui-form-item">
<div class="layui-row">
<div class="layui-col-xs7">
<div class="layui-input-wrap">
<div class="layui-input-prefix">
<i class="layui-icon layui-icon-vercode"></i>
</div>
<input
type="text"
name="captcha"
value=""
lay-verify="required"
placeholder="验证码"
lay-reqtext="请填写验证码"
autocomplete="off"
class="layui-input"
lay-affix="clear"
/>
</div>
</div>
<div class="layui-col-xs5">
<div style="margin-left: 10px">
<img
src="https://www.oschina.net/action/user/captcha"
onclick="this.src='https://www.oschina.net/action/user/captcha?t='+ new Date().getTime();"
/>
</div>
</div>
</div>
</div>
<div class="layui-form-item"> <div class="layui-form-item">
<input <input
type="checkbox" type="checkbox"
name="remember" name="remember"
lay-skin="primary" lay-skin="primary"
title="记住密码" title="记住密码"
checked
/> />
<a href="#forget" style="float: right; margin-top: 7px">忘记密码?</a> <a href="#forget" style="float: right; margin-top: 7px">忘记密码?</a>
</div> </div>
<div class="layui-form-item"> <div class="layui-form-item">
<button <button
class="layui-btn layui-btn-fluid" class="layui-btn layui-btn-fluid login"
lay-submit lay-submit
lay-filter="demo-login" lay-filter="login-in"
> >
登录 登录
</button> </button>
@@ -129,20 +100,31 @@
var form = layui.form; var form = layui.form;
var button = layui.button; var button = layui.button;
var popup = layui.popup; var popup = layui.popup;
var $ = layui.$;
// 登 录 提 交 // 登 录 提 交
form.on("submit(login)", function (data) { form.on("submit(login-in)", function (data) {
/// 验证 /// 验证
/// 登录
/// 动画 /// 动画
button.load({ let btn = button.load({ elem: ".login" });
elem: ".login",
time: 1500, /// 登录
done: function () { $.ajax({
url: "/api/v1/login",
type: "POST",
data: JSON.stringify(data.field),
contentType: "application/json",
success: function (res) {
btn.stop(function () {
popup.success("登录成功", function () { popup.success("登录成功", function () {
location.href = "./index.html"; location.href = "/";
});
});
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
btn.stop(function () {
popup.failure(XMLHttpRequest.responseJSON.message);
}); });
}, },
}); });