2016-07-25 47 views
2

我已经用flask_login编写了Flask服务器。要登录用户,我使用login_user(user),并且我的网站上有一页用@login_required加以保护。作为一个客户,我使用Python请求包,这是代码:Flask服务器上的会话与Python请求包不起作用

import requests 
sess = requests.session() 
sess.post("http://page.on/my/site", data={"login" : "login", "password" : "password"}) 

一切皆与此认证OK,但后来我试图访问受保护的页面:

r = sess.get("http://secure.page/on/the/site") 

而这个请求接收Unauthorized 。 设置身份验证后,这是饼干(现在我有我的本地主机上的服务器):

<RequestsCookieJar[<Cookie session=.eJwdzjkSwjAMAMC_uE4h2dbhfCZjHR5oE1Ix_B2Gbst9l2OdeT3K_jrv3MrxjLKX5tqBGbq7MfmPiYi8aA7RAG8haZJoDZ0HrlSG6Oa1-yCqsaJNJlSVAQToNXsAt8UiFQBIbIa3bmYiarYyiEaNsUJjmlLZyn3l-c_Uzxf_2C6a.Cnf0yA.xIUSIFgcvjqwszrbwCA_D2Rqa5k for localhost.local/>]> 

顺便说一句,我也用这个:

login_manager.session_protection = "strong" 

如何解决此身份验证问题?

UPD:

这是服务器的登录代码:

@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是烧瓶蓝图的名称

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_authenticatedTrue。我使用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 

标识打印正确,它的类型是str,查询工作得很好,但我仍然得到Unauthenticated错误,并在最后的printuser.is_authenticated是假的。

UPD5:

其实user.is_authenticated只是login_user印刷后也显示的是假的,即使我login_user后叫session.commit()

+0

根据文档,当会话保护处于活动状态时,每个请求都会为用户计算机生成一个标识符(基本上是IP地址和用户代理的安全哈希)。因此,它不会看起来这是一个问题。你能发布一个完整的[mcve]吗? –

+0

@WayneWerner,查看我的更新回答 –

+0

您错过了您的问题中的用户加载器和您的用户类,但很可能我的答案解决了您的问题。 –

回答

0

这似乎表现出你解释行为:

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。显然,解码来自会话的ID不够聪明,不知道你的ID只是一个字符串。通过改变我的功能return str(self.id) == '42',它的工作原理。我怀疑你的用户加载器或用户类有类似的设置。

正如我怀疑 - 你的用户模型产生了一个不正确的is_authenticated。当然,它很可能是正好你告诉它。您只需修复已认证的位。请注意,如果您从用户加载程序返回None,它将使用匿名用户 - 您可以在is_authenticated方法中硬编码True,除非您尝试跨会话注销用户。

+1

'Flask-Login' *要求*你的用户ID是一个文本类型(2.7中的'unicode'和3.x中的'str')。请参阅['get_id'](https://flask-login.readthedocs.io/en/latest/#your-user-class)文档。好吧,我想严格来说,你可以重写'get_id'来完成转换,但'get_id'必须返回一个文本类型。 – jpmc26

+0

有用的知道 - 我怀疑'UserMixin'在'get_id'的幕后做了。 –

+0

@WayneWerner,我刚刚尝试过,并添加了一些调试打印,并且问题非常不同 - 请参阅我的更新的答案 –

相关问题