| | 7 | |
|---|
| | 8 | def load_backend(path): |
|---|
| | 9 | i = path.rfind('.') |
|---|
| | 10 | module, attr = path[:i], path[i+1:] |
|---|
| | 11 | try: |
|---|
| | 12 | mod = __import__(module, '', '', [attr]) |
|---|
| | 13 | except ImportError, e: |
|---|
| | 14 | raise ImproperlyConfigured, 'Error importing authentication backend %s: "%s"' % (module, e) |
|---|
| | 15 | try: |
|---|
| | 16 | cls = getattr(mod, attr) |
|---|
| | 17 | except AttributeError: |
|---|
| | 18 | raise ImproperlyConfigured, 'Module "%s" does not define a "%s" authentication backend' % (module, attr) |
|---|
| | 19 | return cls() |
|---|
| | 20 | |
|---|
| | 21 | def get_backends(): |
|---|
| | 22 | from django.conf import settings |
|---|
| | 23 | backends = [] |
|---|
| | 24 | for backend_path in settings.AUTHENTICATION_BACKENDS: |
|---|
| | 25 | backends.append(load_backend(backend_path)) |
|---|
| | 26 | return backends |
|---|
| | 27 | |
|---|
| | 28 | def authenticate(**credentials): |
|---|
| | 29 | """ |
|---|
| | 30 | If the given credentials, return a user object. |
|---|
| | 31 | """ |
|---|
| | 32 | for backend in get_backends(): |
|---|
| | 33 | try: |
|---|
| | 34 | user = backend.authenticate(**credentials) |
|---|
| | 35 | except TypeError: |
|---|
| | 36 | # this backend doesn't accept these credentials as arguments, try the next one. |
|---|
| | 37 | continue |
|---|
| | 38 | if user is None: |
|---|
| | 39 | continue |
|---|
| | 40 | # annotate the user object with the path of the backend |
|---|
| | 41 | user.backend = str(backend.__class__) |
|---|
| | 42 | return user |
|---|
| | 43 | |
|---|
| | 44 | def login(request, user): |
|---|
| | 45 | """ |
|---|
| | 46 | Persist a user id and a backend in the request. This way a user doesn't |
|---|
| | 47 | have to reauthenticate on every request. |
|---|
| | 48 | """ |
|---|
| | 49 | if user is None: |
|---|
| | 50 | user = request.user |
|---|
| | 51 | # TODO: It would be nice to support different login methods, like signed cookies. |
|---|
| | 52 | request.session[SESSION_KEY] = user.id |
|---|
| | 53 | request.session[BACKEND_SESSION_KEY] = user.backend |
|---|
| | 54 | |
|---|
| | 55 | def logout(request): |
|---|
| | 56 | """ |
|---|
| | 57 | Remove the authenticated user's id from request. |
|---|
| | 58 | """ |
|---|
| | 59 | del request.session[SESSION_KEY] |
|---|
| | 60 | del request.session[BACKEND_SESSION_KEY] |
|---|
| | 61 | |
|---|
| | 62 | def get_user(request): |
|---|
| | 63 | from django.contrib.auth.models import AnonymousUser |
|---|
| | 64 | try: |
|---|
| | 65 | user_id = request.session[SESSION_KEY] |
|---|
| | 66 | backend_path = request.session[BACKEND_SESSION_KEY] |
|---|
| | 67 | backend = load_backend(backend_path) |
|---|
| | 68 | user = backend.get_user(user_id) or AnonymousUser() |
|---|
| | 69 | except KeyError: |
|---|
| | 70 | user = AnonymousUser() |
|---|
| | 71 | return user |
|---|