Я пытаюсь создать веб-приложение с помощью Flask. Моя главная страница (/) проверяет, вошел ли кто-нибудь в систему, а если нет, отображает форму с запросом имени пользователя и пароля. Когда пользователь отправляет from, эти учетные данные проверяются, и, если они действительны, пользовательский объект создается и отправляется в flask_login с использованием его функции login_user
:
@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()
выводит код отладки в stderr.)
Я написал отладочный код, чтобы посмотреть, что происходит. Перед каждым запросом печатается файл 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
Обратите внимание, что эта функция также выводит отладочный код при выполнении.
Когда я вхожу в систему с именем пользователя Mike, а затем выполняю GET / запрос, мой stderr выглядит так:
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 -
Обратите внимание, что:
перед запросом файл cookie сеанса имеет правильное имя пользователя Mike
моя функция
load_user()
не вызывается из flask_loginКогда Jinja2 отображает шаблон для /,
current_user
Flask теперь является анонимным пользователем.
Итак, почему flask-login меняет мой current_user
с правильного зарегистрированного пользователя на анонимного? И как мне это исправить?
FWIW, я использую Flask (0.10.1), Flask-Login (0.3.2), это опасно (0.24).
Изменить:
Мой пользовательский класс называется Engineer
. Это класс SQLAlchemy, который также наследуется от класса UserMixin
во Flask-login.
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
К сожалению, функция get_id()
не вызывается, когда flask_login автоматически выводит меня из системы.