login_required装饰器如何起作用:
- 对于使用了login(user=user, remember=remember…)的用户, 即为已登陆的用户:
login_user方法将user_id remember保存到session中
并将user添加到_request_ctx_stack.top.user中
然后当使用current_user时就会从_request_ctx_stack.top中读取到user
判断user的is_authenticated(所有用户的这个值都为True)
这里的语句是:if not current_user.is_authenticated: return current_app.login_manager.unauthorized() return func()
显然就会调用视图函数
- 对于没有登陆的用户
同样的调用这次会执行 current_app.login_mamager.unauthorized()
这个方法返会登陆视图, 如果没有指定, 会抛出401的网页错误
current_user = LocalProxy(lambda: _get_user())
_get_user
if has_request_context() and not hasattr(_request_ctx_stack.top, 'user'):
current_app.login_manager._load_user()
return getattr(_request_ctx_stack.top, 'user', None)
_load_user
config = current_app.config
if config.get('SESSION_PROTECTION', self.session_protection):
deleted = self._session_protection()
if deleted:
return self.reload_user()
is_missing_user_id = 'user_id' not in session
if is_missing_user_id:
cookie_name = config.get('REMEMBER_COOKIE_NAME', COOKIE_NAME)
header_name = config.get('AUTH_HEADER_NAME', AUTH_HEADER_NAME)
has_cookie = (cookie_name in request.cookies and
session.get('remember') != 'clear')
if has_cookie:
return self._load_from_cookie(request.cookies[cookie_name])
elif self.request_callback:
return self._load_from_request(request)
elif header_name in request.headers:
return self._load_from_header(request.headers[header_name])
return self.reload_user()
_load_from_cookie
_load_from_header
_load_from_request
def _load_from_cookie(self, cookie):
user_id = decode_cookie(cookie)
if user_id is not None:
session['user_id'] = user_id
session['_fresh'] = False
self.reload_user()
if _request_ctx_stack.top.user is not None:
app = current_app._get_current_object()
user_loaded_from_cookie.send(app, user=_get_user())
def _load_from_header(self, header):
user = None
if self.header_callback:
user = self.header_callback(header)
if user is not None:
self.reload_user(user=user)
app = current_app._get_current_object()
user_loaded_from_header.send(app, user=_get_user())
else:
self.reload_user()
def _load_from_request(self, request):
user = None
if self.request_callback:
user = self.request_callback(request)
if user is not None:
self.reload_user(user=user)
app = current_app._get_current_object()
user_loaded_from_request.send(app, user=_get_user())
else:
self.reload_user()
reload_user()
ctx = _request_ctx_stack.top
if user is None:
user_id = session.get('user_id')
if user_id is None:
ctx.user = self.anonymous_user()
else:
if self.user_callback is None:
raise Exception(
"No user_loader has been installed for this "
"LoginManager. Refer to"
"https://flask-login.readthedocs.io/"
"en/latest/#how-it-works for more info.")
user = self.user_callback(user_id)
if user is None:
ctx.user = self.anonymous_user()
else:
ctx.user = user
else:
ctx.user = user
self.user_callback
def user_loader(self, callback):
self.user_callback = callback
return callback