Le moteur d’authentification Django (default)

Le module Python https://github.com/django/django/blob/master/django/contrib/auth/backends.py

  1import inspect
  2import warnings
  3
  4from django.contrib.auth import get_user_model
  5from django.contrib.auth.models import Permission
  6from django.utils.deprecation import RemovedInDjango31Warning
  7
  8UserModel = get_user_model()
  9
 10
 11class ModelBackend:
 12    """
 13    Authenticates against settings.AUTH_USER_MODEL.
 14    """
 15
 16    def authenticate(self, request, username=None, password=None, **kwargs):
 17        if username is None:
 18            username = kwargs.get(UserModel.USERNAME_FIELD)
 19        try:
 20            user = UserModel._default_manager.get_by_natural_key(username)
 21        except UserModel.DoesNotExist:
 22            # Run the default password hasher once to reduce the timing
 23            # difference between an existing and a nonexistent user (#20760).
 24            UserModel().set_password(password)
 25        else:
 26            if user.check_password(password) and self.user_can_authenticate(user):
 27                return user
 28
 29    def user_can_authenticate(self, user):
 30        """
 31        Reject users with is_active=False. Custom user models that don't have
 32        that attribute are allowed.
 33        """
 34        is_active = getattr(user, "is_active", None)
 35        return is_active or is_active is None
 36
 37    def _get_user_permissions(self, user_obj):
 38        return user_obj.user_permissions.all()
 39
 40    def _get_group_permissions(self, user_obj):
 41        user_groups_field = get_user_model()._meta.get_field("groups")
 42        user_groups_query = "group__%s" % user_groups_field.related_query_name()
 43        return Permission.objects.filter(**{user_groups_query: user_obj})
 44
 45    def _get_permissions(self, user_obj, obj, from_name):
 46        """
 47        Return the permissions of `user_obj` from `from_name`. `from_name` can
 48        be either "group" or "user" to return permissions from
 49        `_get_group_permissions` or `_get_user_permissions` respectively.
 50        """
 51        if not user_obj.is_active or user_obj.is_anonymous or obj is not None:
 52            return set()
 53
 54        perm_cache_name = "_%s_perm_cache" % from_name
 55        if not hasattr(user_obj, perm_cache_name):
 56            if user_obj.is_superuser:
 57                perms = Permission.objects.all()
 58            else:
 59                perms = getattr(self, "_get_%s_permissions" % from_name)(user_obj)
 60            perms = perms.values_list("content_type__app_label", "codename").order_by()
 61            setattr(
 62                user_obj, perm_cache_name, {"%s.%s" % (ct, name) for ct, name in perms}
 63            )
 64        return getattr(user_obj, perm_cache_name)
 65
 66    def get_user_permissions(self, user_obj, obj=None):
 67        """
 68        Return a set of permission strings the user `user_obj` has from their
 69        `user_permissions`.
 70        """
 71        return self._get_permissions(user_obj, obj, "user")
 72
 73    def get_group_permissions(self, user_obj, obj=None):
 74        """
 75        Return a set of permission strings the user `user_obj` has from the
 76        groups they belong.
 77        """
 78        return self._get_permissions(user_obj, obj, "group")
 79
 80    def get_all_permissions(self, user_obj, obj=None):
 81        if not user_obj.is_active or user_obj.is_anonymous or obj is not None:
 82            return set()
 83        if not hasattr(user_obj, "_perm_cache"):
 84            user_obj._perm_cache = {
 85                *self.get_user_permissions(user_obj),
 86                *self.get_group_permissions(user_obj),
 87            }
 88        return user_obj._perm_cache
 89
 90    def has_perm(self, user_obj, perm, obj=None):
 91        return user_obj.is_active and perm in self.get_all_permissions(user_obj, obj)
 92
 93    def has_module_perms(self, user_obj, app_label):
 94        """
 95        Return True if user_obj has any permissions in the given app_label.
 96        """
 97        return user_obj.is_active and any(
 98            perm[: perm.index(".")] == app_label
 99            for perm in self.get_all_permissions(user_obj)
100        )
101
102    def get_user(self, user_id):
103        try:
104            user = UserModel._default_manager.get(pk=user_id)
105        except UserModel.DoesNotExist:
106            return None
107        return user if self.user_can_authenticate(user) else None
108
109
110class AllowAllUsersModelBackend(ModelBackend):
111    def user_can_authenticate(self, user):
112        return True
113
114
115class RemoteUserBackend(ModelBackend):
116    """
117    This backend is to be used in conjunction with the ``RemoteUserMiddleware``
118    found in the middleware module of this package, and is used when the server
119    is handling authentication outside of Django.
120
121    By default, the ``authenticate`` method creates ``User`` objects for
122    usernames that don't already exist in the database.  Subclasses can disable
123    this behavior by setting the ``create_unknown_user`` attribute to
124    ``False``.
125    """
126
127    # Create a User object if not already in the database?
128    create_unknown_user = True
129
130    def authenticate(self, request, remote_user):
131        """
132        The username passed as ``remote_user`` is considered trusted. Return
133        the ``User`` object with the given username. Create a new ``User``
134        object if ``create_unknown_user`` is ``True``.
135
136        Return None if ``create_unknown_user`` is ``False`` and a ``User``
137        object with the given username is not found in the database.
138        """
139        if not remote_user:
140            return
141        user = None
142        username = self.clean_username(remote_user)
143
144        # Note that this could be accomplished in one try-except clause, but
145        # instead we use get_or_create when creating unknown users since it has
146        # built-in safeguards for multiple threads.
147        if self.create_unknown_user:
148            user, created = UserModel._default_manager.get_or_create(
149                **{UserModel.USERNAME_FIELD: username}
150            )
151            if created:
152                args = (request, user)
153                try:
154                    inspect.getcallargs(self.configure_user, request, user)
155                except TypeError:
156                    args = (user,)
157                    warnings.warn(
158                        "Update %s.configure_user() to accept `request` as "
159                        "the first argument." % self.__class__.__name__,
160                        RemovedInDjango31Warning,
161                    )
162                user = self.configure_user(*args)
163        else:
164            try:
165                user = UserModel._default_manager.get_by_natural_key(username)
166            except UserModel.DoesNotExist:
167                pass
168        return user if self.user_can_authenticate(user) else None
169
170    def clean_username(self, username):
171        """
172        Perform any cleaning on the "username" prior to using it to get or
173        create the user object.  Return the cleaned username.
174
175        By default, return the username unchanged.
176        """
177        return username
178
179    def configure_user(self, request, user):
180        """
181        Configure a user after creation and return the updated user.
182
183        By default, return the user unmodified.
184        """
185        return user
186
187
188class AllowAllUsersRemoteUserBackend(RemoteUserBackend):
189    def user_can_authenticate(self, user):
190        return True