我已经用 flask_login 编写了 Flask 服务器。要登录用户,我使用 login_user(user)
,并且我的网站有一页受 @login_required
保护.作为客户端,我使用 Python requests 包,代码如下:
import requests
sess = requests.session()
sess.post("http://page.on/my/site", data={"login" : "login", "password" : "password"})
此身份验证一切正常,但随后我尝试访问 protected 页面:
r = sess.get("http://secure.page/on/the/site")
这个请求接收到
Unauthorized
.这是身份验证后设置的 cookie(现在我的服务器在 localhost 上):
<RequestsCookieJar[<Cookie session=.eJwdzjkSwjAMAMC_uE4h2dbhfCZjHR5oE1Ix_B2Gbst9l2OdeT3K_jrv3MrxjLKX5tqBGbq7MfmPiYi8aA7RAG8haZJoDZ0HrlSG6Oa1-yCqsaJNJlSVAQToNXsAt8UiFQBIbIa3bmYiarYyiEaNsUJjmlLZyn3l-c_Uzxf_2C6a.Cnf0yA.xIUSIFgcvjqwszrbwCA_D2Rqa5k for localhost.local/>]>
顺便说一句,我也用这个:
login_manager.session_protection = "strong"
如何解决此身份验证问题?
升级版:
这是服务器登录代码:
@api.route("/login/", methods=["POST"])
def handle_login_request():
login, password = str(request.form['login']).lower(), str(request.form['password'])
# Get and check user here
login_user(user)
# update user and get user_data
return jsonify(user_data)
安全路线:
@api.route("/users_of_group/")
@login_required
def get_user_of_users_group():
# code here never executes because of @login_required
api
是 flask 蓝图的名称UPD2:
这是
sess.get
返回的页面内容: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>401 Unauthorized</title>
<h1>Unauthorized</h1>
<p>The server could not verify that you are authorized to access the URL requested. You either supplied the wrong credentials (e.g. a bad password), or your browser doesn't understand how to supply the credentials required.</p>
UPD3:
我试着用这个:
r = sess.get("http://secure.page/on/the/site", auth=("login", "password"))
在我可以看到的服务器上,首先用户已成功登录,但随后服务器仍然抛出 401。
import requests
sess = requests.session()
login = sess.post("http://page.on/my/site", data={"login" : "login", "password" : "password"})
r = sess.get("http://secure.page/on/the/site", cookies=login.cookies)
还登录用户,然后抛出 401。
UPD4:
问题似乎在 login_user 函数中,它不会改变
is_authenticated
至True
.我使用 SQLAlchemy,这是我的用户类:class User(db.Model):
user_id = db.Column(db.Integer, primary_key=True)
# Many required for my app fields
is_active = db.Column(db.Boolean, default=False)
is_authenticated = db.Column(db.Boolean, default=False)
is_anonymous = db.Column(db.Boolean, default=False)
is_online = db.Column(db.Boolean, default=False)
# Init function
def get_id(self):
return str(self.user_id)
和
user_loader
:@login_manager.user_loader
def load_user(user_id):
print(user_id, type(user_id))
user = User.query.filter_by(user_id=int(user_id)).first()
print(user.login, user.is_authenticated)
return user
id打印正确,其类型为
str
,查询工作正常,但我仍然得到 Unauthenticated
错误,在最后 print
user.is_authenticated
是假的。UPD5:
实际上,打印
user.is_authenticated
就在 login_user
之后也显示 False,即使我调用了 session.commit()
在 login_user
之后.
最佳答案
这似乎表现出您解释的行为:
from flask import Flask, request
from flask_login import LoginManager, UserMixin, login_user, login_required, \
current_user
app = Flask(__name__)
app.secret_key = 'This is totally a secret'
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.session_protection = 'strong'
class User(UserMixin):
id = 42
@property
def is_authenticated(self):
print('{!r}'.format(self.id))
return self.id == 42
@login_manager.user_loader
def get_user(id):
user = User()
user.id = id
return user
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
user = User()
user.id = request.form.get('id', 42)
login_user(user)
else:
user = current_user
return 'Okay, logged in with id {}'.format(user.id)
@app.route('/')
@login_required
def main():
return 'Hey cool - your id {}'.format(current_user.id)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5001, debug=True)
这里要注意的是ID是
'42'
,而不是 42
.显然,从 session 中解码 id 还不够聪明,无法知道您的 ID 不是字符串。通过将我的功能更改为 return str(self.id) == '42'
, 有用。我怀疑您的用户加载器或用户类中有类似的设置。正如我所怀疑的 - 您的用户模型产生了不正确的
is_authenticated
.当然,它很可能完全按照您的指示行事。您只需修复经过身份验证的位。请注意,如果您返回 None
从您的用户加载器中得知它将使用匿名用户 - 您可以硬编码 True
在您的 is_authenticated
方法,除非您尝试跨 session 注销用户。
关于python - 带有 Python 请求包的 Flask 服务器上的 session 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38575888/