flask login

介绍

使用flask-login很方便的来保存用户的登陆状态。

常用的有

1
2
3
from flask_login import current_user, login_required, login_user, logout_user

@login_manager.user_loader

login_user和logout_user

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
def login_user(user, remember=False, force=False, fresh=True):
if not force and not user.is_active:
return False
# current_app.login_manager.id_attribut 即 get_id,也就变成 user.get_id(),
# 这也就是为什么user model 需要重写 get_id的原因,而不必强行规定写是因为继承的
# UserMixin 实现了 get_id() 方法
user_id = getattr(user, current_app.login_manager.id_attribute)()
session[‘user_id’] = user_id
session[‘_fresh’] = fresh
session[‘_id’] = _create_identifier()

if remember:
session[‘remember’] = ‘set’

# 将该user放到请求上下文的栈上
_request_ctx_stack.top.user = user
# 发送用户登陆的信号
user_logged_in.send(current_app._get_current_object(), user=_get_user())
return True

def logout_user():
# 从ctx取的user
user = _get_user()

if ‘user_id’ in session:
session.pop(‘user_id’)

if ‘_fresh’ in session:
session.pop(‘_fresh’)

cookie_name = current_app.config.get(‘REMEMBER_COOKIE_NAME’, COOKIE_NAME)
if cookie_name in request.cookies:
session[‘remember’] = ‘clear’
#发送信号
user_logged_out.send(current_app._get_current_object(), user=user)

current_app.login_manager.reload_user()
return True

login_required

判断current_user是否登录,否则会找到app的login_view,使用redrect重定向。

1
2
3
4
5
6
7
8
9
def login_required(func):
@wraps(func)
def decorated_view(args, **kwargs):
if current_app.login_manager._login_disabled:
return func(args, kwargs)
elif not current_user.is_authenticated:
return current_app.login_manager.unauthorized()
return func(*args, kwargs)
return decorated_view

current_user

使用了werlzeng 的 LocalProxy代理获取到ctx top的user

user_loader

就是将装饰的方法作为了回调函数用来通过id获取到user对象

一个问题

在一些例子上验证当前用户是否登陆时使用的是current_user.is_authenticated(),自己使用会发生错误,

在代码中的 UserMixin类实现这几个方法,但是使用了@property

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class UserMixin(object):
@property
def is_active(self):
return True

@property
def is_authenticated(self):
return True

@property
def is_anonymous(self):
return False

def get_id(self):
try:
return unicode(self.id)
except AttributeError:
raise NotImplementedError(‘No id attribute - override get_id)

所以使用current_user.is_authenticated即可,之前的用法有两种可能:

  • 版本问题,在0.3.0之前包括0.3.0使用current_user.is_authenticated()
  • 在 User model 中重写了方法,不使用@property,两种方式都可用