import datetime from django.core.exceptions import ImproperlyConfigured SESSION_KEY = '_auth_user_id' BACKEND_SESSION_KEY = '_auth_user_backend' REDIRECT_FIELD_NAME = 'next' def load_backend(path): i = path.rfind('.') module, attr = path[:i], path[i+1:] try: mod = __import__(module, {}, {}, [attr]) except ImportError, e: raise ImproperlyConfigured, 'Error importing authentication backend %s: "%s"' % (module, e) except ValueError, e: raise ImproperlyConfigured, 'Error importing authentication backends. Is AUTHENTICATION_BACKENDS a correctly defined list or tuple?' try: cls = getattr(mod, attr) except AttributeError: raise ImproperlyConfigured, 'Module "%s" does not define a "%s" authentication backend' % (module, attr) return cls() def get_backends(): from django.conf import settings backends = [] for backend_path in settings.AUTHENTICATION_BACKENDS: backends.append(load_backend(backend_path)) return backends def authenticate(**credentials): """ If the given credentials are valid, return a User object. """ for backend in get_backends(): try: user = backend.authenticate(**credentials) except TypeError: # This backend doesn't accept these credentials as arguments. Try the next one. continue if user is None: continue # Annotate the user object with the path of the backend. user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__) return user def login(request, user): """ Persist a user id and a backend in the request. This way a user doesn't have to reauthenticate on every request. """ if user is None: user = request.user # TODO: It would be nice to support different login methods, like signed cookies. user.last_login = datetime.datetime.now() user.save() if request.session.get('SESSION_KEY', user.id) != user.id: # To avoid reusing another user's session, create a new, empty session # if the existing session corresponds to a different authenticated user. request.session.flush() request.session[SESSION_KEY] = user.id request.session[BACKEND_SESSION_KEY] = user.backend if hasattr(request, 'user'): request.user = user def logout(request): """ Removes the authenticated user's ID from the request and flushes their session data. """ request.session.flush() if hasattr(request, 'user'): from django.contrib.auth.models import AnonymousUser request.user = AnonymousUser() def get_user(request): from django.contrib.auth.models import AnonymousUser try: user_id = request.session[SESSION_KEY] backend_path = request.session[BACKEND_SESSION_KEY] backend = load_backend(backend_path) user = backend.get_user(user_id) or AnonymousUser() except KeyError: user = AnonymousUser() return user