2017-01-18 1 views
0

사용자가 처음 로깅 할 때 클라이언트에 대한 응답으로 고유 한 sessionID를 가진 세션 개체를 만든 다음 사용자가 다른 사용자에게 해당 ID로 쿠키를 요청하면 서버가 해당 세션 개체를 찾을 수 있음을 알고 있습니다. 사용자가 로그인했음을 나타내는 ID!flasks-login은 signgle 세션으로 로그인 한 다른 사용자를 어떻게 식별합니까?

하지만 이것은 하나의 사용자 상황입니다. 모든 사용자에게 많은 세션을 메모리에 만들어야하는 경우 대부분의 블로그에서 관리 할 사용자가 많은지 알 수 없습니다. 나도 그렇게 생각해!

플라스크 로그인 소스 코드를 조회 할 때 모든 사용자에 대해 세션을 유지하기 위해 세션 모음을 찾을 수 없습니까?

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 

사용자를 유지하는 세션이 있지만 다른 사용자가 방문하면 어떻게됩니까? 내가 세션 찾을

# -*- coding: utf-8 -*- 
""" 
    flask.globals 
    ~~~~~~~~~~~~~ 

    Defines all the global objects that are proxies to the current 
    active context. 

    :copyright: (c) 2011 by Armin Ronacher. 
    :license: BSD, see LICENSE for more details. 
""" 

from functools import partial 
from werkzeug.local import LocalStack, LocalProxy 


def _lookup_req_object(name): 
    top = _request_ctx_stack.top 
    if top is None: 
     raise RuntimeError('working outside of request context') 
    return getattr(top, name) 


def _lookup_app_object(name): 
    top = _app_ctx_stack.top 
    if top is None: 
     raise RuntimeError('working outside of application context') 
    return getattr(top, name) 


def _find_app(): 
    top = _app_ctx_stack.top 
    if top is None: 
     raise RuntimeError('working outside of application context') 
    return top.app 


# context locals 
_request_ctx_stack = LocalStack() 
_app_ctx_stack = LocalStack() 
current_app = LocalProxy(_find_app) 
request = LocalProxy(partial(_lookup_req_object, 'request')) 
session = LocalProxy(partial(_lookup_req_object, 'session')) 
g = LocalProxy(partial(_lookup_app_object, 'g')) 

는 글로벌 변수 및 localstack가) (하지만, 작동 않는 방법을 나는 아직도 konw하지?

class Local(object): 
    __slots__ = ('__storage__', '__ident_func__') 

    def __init__(self): 
     object.__setattr__(self, '__storage__', {}) 
     object.__setattr__(self, '__ident_func__', get_ident) 

    def __iter__(self): 
     return iter(self.__storage__.items()) 

    def __call__(self, proxy): 
     """Create a proxy for a name.""" 
     return LocalProxy(self, proxy) 

    def __release_local__(self): 
     self.__storage__.pop(self.__ident_func__(), None) 

    def __getattr__(self, name): 
     try: 
      return self.__storage__[self.__ident_func__()][name] 
     except KeyError: 
      raise AttributeError(name) 

    def __setattr__(self, name, value): 
     ident = self.__ident_func__() 
     storage = self.__storage__ 
     try: 
      storage[ident][name] = value 
     except KeyError: 
      storage[ident] = {name: value} 

    def __delattr__(self, name): 
     try: 
      del self.__storage__[self.__ident_func__()][name] 
     except KeyError: 
      raise AttributeError(name) 

많은 사람들은, storage[ident][name] = value를 식별하기 위해 다른 스레드 ID를 사용 말하지만, 난 스레딩 비활성화, 그것은 다중 사용자를 위해 잘 작동? 나는 current_user 변수를 사용하여 현재 사용자를 식별하지만 current_user는 매우 마술 적이다. 그것은 문제를 해결하기 위해 사용자 세션 컬렉션을 유지하는 것이 아니라 하나의 current_user를 유지합니다! 어떻게 작동하는지 모르겠다.

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 

쿠키와 현재 사용자 세션 ID를 서버가 비교 한 세션 수집과 비교하는 프로세스는 어디입니까? 아무도 나 도와 줄 수 없어?

답변

0

나는 flask-login/flask_login/login_manager.py:_load_user()

살펴 난 당신이 SESSION_PROTECTION에 대해 이야기하고 생각을. 이 경우 사용자를 다시로드하는 방법은 기본 또는 강력한 인증 모드에 따라 다릅니다. 세션 보호 기능이없는 경우 플라스크는 요청, 헤더 또는 쿠키에서 사용자를로드하려고 시도합니다.

class LoginManager(object): 
... 

def _load_user(self): 
    '''Loads user from session or remember_me cookie as applicable''' 
    user_accessed.send(current_app._get_current_object()) 

    # first check SESSION_PROTECTION 
    config = current_app.config 
    if config.get('SESSION_PROTECTION', self.session_protection): 
     deleted = self._session_protection() 
     if deleted: 
      return self.reload_user() 

    # If a remember cookie is set, and the session is not, move the 
    # cookie user ID to the session. 
    # 
    # However, the session may have been set if the user has been 
    # logged out on this request, 'remember' would be set to clear, 
    # so we should check for that and not restore the session. 
    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() 

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() 

플라스크는 콜백에 요청을 전달합니다. 플라스크 로그인은 좋은 질문이 있으시면 example(Custom Login using Request Loader) 어떻게 사용자를로드 할 수 있습니다.

@login_manager.request_loader 
def load_user_from_request(request): 

# first, try to login using the api_key url arg 
api_key = request.args.get('api_key') 
if api_key: 
    user = User.query.filter_by(api_key=api_key).first() 
    if user: 
     return user 

# next, try to login using Basic Auth 
api_key = request.headers.get('Authorization') 
if api_key: 
    api_key = api_key.replace('Basic ', '', 1) 
    try: 
     api_key = base64.b64decode(api_key) 
    except TypeError: 
     pass 
    user = User.query.filter_by(api_key=api_key).first() 
    if user: 
     return user 

# finally, return None if both methods did not login the user 
return None 

api_key는 한 물리적 시스템의 다른 로그인에 대해 클라이언트가 백엔드를 통해 권한을 부여받을 때 지정할 수 있습니다.

+0

요청 또는 쿠키에서 왔습니까? 하지만 이것은 클라이언트에서 오는 것입니다, 나는 서버가 사용자 세션 콜렉션으로 메모리에 기록함으로써 사용자를 기억한다고 생각합니다. 따라서 사용자가 기록한 경우 콜렉션에 하나의 세션이 있으며 사용자가 기록 된 상태가 유지 될 수 있습니다 . 요청에서 사용자를로드한다고 해, 이해가 안되니? – kitian

+0

@kitian 나는 나의 대답을 확장했다. – theodor

관련 문제