我将后端和前端分开。后端是用flask编写的,前端是简单的js,带有fetch请求与后端交互。
身份验证是在后端使用 Flask 登录完成的,我用 @login_required 装饰了一些端点。
问题是我使用http代码200正确登录,但是当我想用js请求一些enpoints时,我的@login_required导致401未经授权的错误。注意到我在不同的蓝图中分开了我的路线。
我检查并发现登录后我有一个会话ID,它与我在完成请求的fund_request_bp蓝图中获得的会话ID不同。我还指出,当我调用 Fund_request_bp 蓝图中的所有端点时,我具有相同的会话 ID。
登录码
from config import app, db, login_manager, default_password
from models import User
from flask import Blueprint, request, jsonify, render_template, redirect, url_for, flash, session
from flask_login import login_user, logout_user, login_required, current_user
user_bp = Blueprint("user", __name__)
@user_bp.route('/login', methods=['POST'])
def login():
data = request.form
user = User.query.filter_by(username=data.get('username')).first()
if (user and user.check_password(data.get('password')) and data.get('password')==default_password):
return jsonify({"message": "Redirect To Change Password !"}), 303
elif (user and user.check_password(data.get('password'))):
login_user(user)
session['test'] = 'valuetest'
print(session.sid)
return jsonify({"message": "Login successfully"}), 200
else:
return jsonify({"error": "Invalid username or password."}), 404
其他蓝图
fund_request_bp = Blueprint("fund_request", __name__, url_prefix="/fund_requests")
@fund_request_bp.route("/", methods=["GET"])
@login_required
def get_all_fund_request():
fund_requests = FundRequest.query.filter_by(approval_level=current_user.user_level.level)
if fund_requests.first() is None:
return jsonify({"message": "No Funds request found."}), 200
fund_requests_serialized = [fund_request.serialize() for fund_request in fund_requests]
return jsonify(fund_requests_serialized), 200
js代码
fetch(api_base+"/fund_requests", {
credentials: 'include'
})
.then(response => response.json())
.then(data => {
console.log(data)
})
.catch(error => {
console.error("Error fetching data:", error);
});
这是我的配置
app = Flask(__name__)
app.config['SECRET_KEY'] = 'some_secret_key'
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_COOKIE_PATH'] = '/'
login_manager = LoginManager(app)
CORS(app, supports_credentials=True)
Session(app)
Ps:我使用邮递员进行测试,没有遇到任何问题
我希望请求能够进入端点,而不会被 @login_required 装饰器阻止。
我找到了解决方案,我们需要在 js 中使用 fetch 完成的每个请求中添加 credentials: 'include' 。我没有将其添加到登录请求中。
fetch( '/login',{
method: 'POST',
body: data,
credentials: 'include'
},)
.then(response=> {
console.log(response.status);
})
.catch (err => {
console.log(err.message);
});