问题描述:
在一个flask应用程序上设计登录界面,登录后,另一个flask应用可以获取当前的登录状态。
问题解决思路:
session的共享,首先将登录的session存储到redis中,然后另外一个flask获取当前的session状态,通过user_id来判断当前的登录状态。login_user()函数会将user_id存入,logout_user()会将用户的user_id进行弹出。以下为login_user logout_user的源码:
def login_user(user, remember=False, force=False, fresh=True):
‘’’
Logs a user in. You should pass the actual user object to this. If the
user’s is_active
property is False
, they will not be logged in
unless force
is True
.
This will return ``True`` if the log in attempt succeeds, and ``False`` if
it fails (i.e. because the user is inactive).
:param user: The user object to log in.
:type user: object
:param remember: Whether to remember the user after their session expires.
Defaults to ``False``.
:type remember: bool
:param force: If the user is inactive, setting this to ``True`` will log
them in regardless. Defaults to ``False``.
:type force: bool
:param fresh: setting this to ``False`` will log in the user with a session
marked as not "fresh". Defaults to ``True``.
:type fresh: bool
'''
if not force and not user.is_active:
return False
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'
_request_ctx_stack.top.user = user
user_logged_in.send(current_app._get_current_object(), user=_get_user())
return True
def logout_user():
‘’’
Logs a user out. (You do not need to pass the actual user.) This will
also clean up the remember me cookie if it exists.
‘’’
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
代码实现:
首先,应用1的配置:用的是MySQL数据库
DATABASE_URL=‘mysql+pymysql://root:root@127.0.0.1/flask’
SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
'sqlite:///' + os.path.join(basedir, 'app.db')
REDIS_URL=os.environ.get('REDIS_URL') or 'redis://'
SESSION_TYPE=os.environ.get('SESSION_TYPE') or 'redis'
SESSION_PERMANENT=os.environ.get('SESSION_PERMANENT') or False
SESSION_USE_SIGNER=os.environ.get('SESSION_USE_SIGNER') or False
SESSION_KEY_PREFIX=os.environ.get('SESSION_KEY_PREFIX') or 'session:'
REDIS_HOST=os.environ.get('REDIS_HOST') or '127.0.0.1'
REDIS_PORT=os.environ.get('REDIS_PORT') or '6379'
REDIS_PASSWORD=os.environ.get('REDIS_PASSWORD') or ''
SESSION_REDIS=redis.Redis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD)
PERMANENT_SESSION_LIFETIME= datetime.timedelta(seconds=30*60)
SESSION_TYPE=os.environ.get('SESSION_TYPE') or 'redis'
SESSION_PERMANENT=os.environ.get('SESSION_PERMANENT') or False
SESSION_USE_SIGNER=os.environ.get('SESSION_USE_SIGNER') or False
SESSION_KEY_PREFIX=os.environ.get('SESSION_KEY_PREFIX') or 'session:'
REDIS_HOST=os.environ.get('REDIS_HOST') or '127.0.0.1'
REDIS_PORT=os.environ.get('REDIS_PORT') or '6379'
REDIS_PASSWORD=os.environ.get('REDIS_PASSWORD') or ''
SESSION_REDIS=redis.Redis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD)
PERMANENT_SESSION_LIFETIME= datetime.timedelta(seconds=30*60)
def is_login(func):
@functools.wraps(func)
def inner(*args,**kwargs):
user = session.get('user_id')
if not user:
return redirect('login')
return func(*args,**kwargs)
return inner
def login_required(func):
'''
If you decorate a view with this, it will ensure that the current user is
logged in and authenticated before calling the actual view. (If they are
not, it calls the :attr:`LoginManager.unauthorized` callback.) For
example::
@app.route('/post')
@login_required
def post():
pass
If there are only certain times you need to require that your user is
logged in, you can do so with::
if not current_user.is_authenticated:
return current_app.login_manager.unauthorized()
...which is essentially the code that this function adds to your views.
It can be convenient to globally turn off authentication when unit testing.
To enable this, if the application configuration variable `LOGIN_DISABLED`
is set to `True`, this decorator will be ignored.
.. Note ::
Per `W3 guidelines for CORS preflight requests
<http://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0>`_,
HTTP ``OPTIONS`` requests are exempt from login checks.
:param func: The view function to decorate.
:type func: function
'''
@wraps(func)
def decorated_view(*args, **kwargs):
if request.method in EXEMPT_METHODS:
return func(*args, **kwargs)
elif 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
总体大概应该就是这样了。
参考文章
https://www.py.cn/kuangjia/flask/11390.html
原文地址:https://blog.csdn.net/lsyhaoshuai/article/details/110528498
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。