2016-02-10 57 views
2

我正尝试使用Flask构建Web应用程序。我的首页(/)会检查是否有人登录,如果不是,请显示要求输入用户名和密码的表单。 Whne用户从提交,这些凭证被验证,并且如果有效用户对象被创建和发送使用其login_user功能flask_login:Flask-Login将我登录,但每当我做GET请求时,立即再次登出我

@app.route('/', methods=['POST', 'GET']) 
def front(): 
    tem = jinjaEnv.get_template("front_page.html") 
    msg = "(no message)" 
    if request.method=='POST': 
     un = request.form['username'] 
     pw = request.form['password'] 
     user = modsal.getUser(un, pw) 
     if user.is_authenticated: 
      login_user(user) 
      msg = ("<span style='color:#080; background:#efe;'>" 
        "<i class='fa fa-check-circle'></i> " 
        "You are logged in</span>") 
     else: 
      msg = ("<span style='color:#800; background:#fee;'>" 
        "<i class='fa fa-times-circle'></i> " 
        "login failed</span>") 
    #//if 
    h = tem.render(
     msg = msg, 
    ) 
    return h 

这工作得很好,并且用户已登录

但是,当我对另一个页面(甚至是同一个页面)执行GET请求时,flask-login会将我注销。我有一个user_loader回调,但它没有被flask_login称为:

@loginManager.user_loader 
def load_user(userId): 
    """ returns a user object (for Flask_login). 
    Given a userId (which is the username), returns an Engineer object 
    (if it was a valid user), or None if not. 
    @return Engineer|None 
    """ 
    pr("%s-=-=- userId=%r -=-=-%s", 
     termcolours.TermColours.MAGENTA, 
     userId, 
     termcolours.TermColours.NORMAL) 
    from modsal import session, Engineer 
    u = session.query(Engineer).filter(
     Engineer.username == username).one_or_none() 

    # Note that if a user wasn't found, (u) will be None 
    # here, which is what loginManager wants. 
    return u 

(注:pr()打印调试代码到标准错误。)

我写了一些调试代码,看看发生了什么事情。每个请求之前,该打印会话cookie:

@app.before_request 
def checkSessionCookie(): 
    sessionStr = request.cookies.get('session_8210') 
    decoded = decookie.decodeCookie(sessionStr) 
    pr("%s***** decoded=%s%s", 
     termcolours.TermColours.MAGENTA, 
     decoded, 
     termcolours.TermColours.NORMAL) 

在我Jinja2的模板,我在显示已登录用户的用户名每个页面顶部的一面旗帜。这是通过调用currentUserName(),它返回一个包含用户名的字符串,或""如果没有实现:

def currentUserName(): 
    pr("%s current_user=%s %s", 
     termcolours.TermColours.RED, 
     current_user, 
     termcolours.TermColours.NORMAL) 
    if (not current_user) or current_user.is_anonymous: 
     prvars("current_user") 
     return "" 
    try: 
     un = str(current_user.username) 
     prvars("un") 
     return un 
    except: 
     return "" 
jinjaEnv.globals['currentUserName'] = currentUserName 

注意,这个函数在执行时还会打印出调试代码。

当我与麦克的用户名登录,然后做一个GET /请求,我的标准错误是这样的:

checkSessionCookie():113: ***** decoded={"_fresh":true,"_id":{" b":"MDY5N2MyNDhmZGU4YWVmZmE5NzMzNjEwODQwYmE2NWNhMmU2YzI4MDRiMWZlMmRiNmFhYjg2MmE5NDMyMGY2Y2RiYjBjMTNjOWYzMjE3ODk0YWVmMDk1YjA2ZWJlZjkyNmQ3MDE1MDdkZjI2MDRhNzg2MTI1NzFkOTU0MmJkM2M="},"csrf_token":{" b":"MTVlNGY4MDBjNWQwNThmODhjNzc2ZGZlMzRjODllNmQ5YzU5MWZlMA=="},"user_id":"Mike"} 
currentUserName():72: current_user=<flask_login.AnonymousUserMixin object at 0x7f2f10bff690> 
currentUserName():74 
127.0.0.1 - - [10/Feb/2016 11:54:51] "GET/HTTP/1.1" 200 - 

需要注意的是:

  1. 请求之前,会话cookie有正确的用户名称Mike

  2. my load_user()函数不会被flask_login调用

  3. 当Jinja2的呈现为/模板,瓶的current_user现在是匿名用户

那么,为什么烧瓶登录改变我current_user从正确的登录用户,一位不愿透露姓名吗?我该如何解决这个问题?我使用Flask(0.10.1),Flask-Login(0.3.2),其危险性(0.24)。

编辑:

我的用户类被称为Engineer。这是一个SQLAlchemy类,它也从Flask-login的UserMixin继承。

class Engineer(Base, UserMixin): 
    __tablename__ = 'tblEngineers' 
    engineerId = Column('EngineerID', Integer(), primary_key=True) 
    username = Column('Username', String()) 
    password = Column('Password', String()) 
    firstName = Column('FirstName', String()) 
    lastName = Column('LastName', String()) 
    engineer = Column('Engineer', Integer()) 

    def __repr__(self): 
     s = "<Engineer %d %r %r>" % (
      self.engineerId, self.username, self.engineer) 
     return s 

    #========== stuff Flask-login needs: ========== 
    def get_id(self): 
     result = unicode(self.username) 
     pr("get_id() => %r", result) 
     return result 

不幸的是,当flask_login自动将我注销时,get_id()函数没有被调用。

回答

0

您需要检查您的用户模型。你需要确保模型返回你想要使用的正确的ID。默认情况下,它会通过模型的id属性加载,但我看到您使用的是用户名。你可能需要添加:

def get_id(self): 
    return self.username 

你可以看到根据您提交here.

+0

的用户名和密码的代码的例子都验证了'用户= modsal.getUser(联合国,PW)'。此外,目前我更关心的是**而不是安全。 –

+0

@PhilHunt,我已经更新了我的答案。我能够重现您的问题这是您的用户模型上的get_id。请检查上面的解决方案。 – m1yag1

+0

我'get_id()'函数看起来像这样 高清get_id(个体经营): 结果=的Unicode(self.username) PR( “get_id()=>%R”,结果) 返回结果 不幸的是,不会被调用。 –

相关问题