Categorías
Python

Entrevista con Kenneth comunidad Python Reitz

 

Tabla de Contenidos

  • Modelo PermissionsHow para comprobar PermissionsHow para hacer cumplir PermissionsDjango Admin y modelo de permisos
  • a comprobar los permisos
  • Cómo hacer cumplir los permisos
  • Django Admin y modelo de permisos
  • Implementar los roles de negocio personalizado en Django AdminSetup: A Custom usuario AdminPrevent actualización de FieldsConditionally Prevenir la actualización de FieldsPrevent Los no superusuarios de conceder superusuario RightsGrant Permisos Sólo Usando GroupsPrevent Los no superusuarios editen sus propios PermissionsOverride PermissionsRestrict acceso a Personalizado acciones de instalación
  • : usuario una administración
  • Prevenir Actualizar de campos
  • condicionalmente Prevenir la actualización de campos
  • impedir que los no superusuarios de conceder derechos de superusuario
  • Conceder permisos Sólo Uso de grupos
  • impedir que los no superusuarios editen su propia anulación de permisos
  • Permisos
  • restringir el acceso t o acciones personalizadas
  • Conclusión
  • Cómo comprobar permisos
  • Cómo hacer cumplir los permisos
  • Django de administración y configuración del modelo de permisos
  • : usuario una administración
  • Prevenir la actualización de campos
  • condicionalmente Prevenir la actualización de campos
  • impedir que los no superusuarios de conceder superusuario derechos
  • Conceder permisos Sólo Uso de grupos
  • impedir que los no superusuarios editen su propia anulación de permisos
  • Permisos
  • restringir el acceso a acciones personalizadas

gestión de usuarios en Django admin es una tema complicado. Si exige demasiados permisos, entonces es posible que interfiera con las operaciones del día a día. Si permite que los permisos que se conceden libremente sin supervisión, a continuación, poner el sistema en situación de riesgo.

Django proporciona un buen marco de autenticación con una estrecha integración con Django administrador. Fuera de la caja, Django administrador no impone restricciones especiales al usuario admin. Esto puede llevar a situaciones peligrosas que podrían comprometer su sistema.

¿Sabías usuarios del personal que manejan otros usuarios en el administrador puede editar sus propios permisos? ¿Sabías que también puede hacerse superusuarios? No hay nada en Django de administración que evita que, por lo que toca a usted!

Al final de este tutorial, usted sabrá cómo proteger su sistema:

  • Protege contra la escalada de permiso de impedir a los usuarios editar sus propios permisos
  • permisos Keep ordenada y fácil de mantener sólo obliga a los usuarios a gestionar los permisos Sólo el uso de grupos de permisos
  • Evitar que escapa a través de acciones personalizadas mediante la aplicación de forma explícita los permisos necesarios

lo sigue:

para seguir este tutorial, lo mejor es configurar un proyecto pequeño para jugar. Si no está seguro de cómo hacer eso, entonces echa un vistazo a Empezar a usar Django.

Este tutorial también asume un conocimiento básico de gestión de usuarios de Django. Si usted no está familiarizado con eso, entonces echa un vistazo a la documentación oficial. Bono

gratuito: Haga clic aquí para obtener acceso a una guía gratuita Django Recursos de Aprendizaje (PDF) que le muestra sugerencias y trucos, así como los errores comunes a evitar al crear aplicaciones web Python + Django.

modelo de permisos

permisos son difíciles. Si no se establece permisos, a continuación, poner el sistema en riesgo de intrusos, las fugas de datos y errores humanos. Si abusa de permisos o los usa demasiado, entonces corre el riesgo de interferir con las operaciones del día a día.

Django viene con un sistema de autenticación incorporado. El sistema de autenticación incluye a los usuarios, grupos y permisos.

Cuando se crea un modelo, Django creará automáticamente cuatro permisos predeterminados para las siguientes acciones: Los nombres de permisos

siguen una convención de nomenclatura muy específico: _ .. La ruptura de

dejar que eso abajo:

  • es el nombre de la aplicación. Por ejemplo, el modelo de usuario se importa de la aplicación auth (django.contrib.auth).
  • es una de las acciones anteriores (añadir, borrar, cambiar o vista).
  • es el nombre del modelo, en letras minúsculas.

Conociendo esta convención puede ayudarle a gestionar permisos con mayor facilidad. Por ejemplo, el nombre del permiso para cambiar un usuario es auth.change_user.

Cómo comprobar permisos Permisos

modelo se otorgan a los usuarios o grupos. Para comprobar si un usuario tiene una cierta permiso, puede hacer lo siguiente: el valor de

>>> from django.contrib.auth.models import User
>>> u = User.objects.create_user(username='haki')
>>> u.has_perm('auth.change_user')
False

Es de mencionar que .has_perm () siempre devuelve True para superusuario activa, incluso si el permiso no existe realmente:

>>> from django.contrib.auth.models import User
>>> superuser = User.objects.create_superuser(
... username='superhaki',
... email='me@hakibenita.com',
... password='secret',
)
>>> superuser.has_perm('does.not.exist')
True

Como puede ver, cuando usted está comprobando los permisos de superusuario, los permisos están en realidad no se está comprobando.

Cómo hacer cumplir los modelos de permisos

Django no hacen cumplir permisos a sí mismos. El único lugar permisos se aplican fuera de la caja por defecto es de Django administrador.

Los modelos razón no hacen cumplir los permisos es que, normalmente, el modelo no se da cuenta del usuario que realiza la acción. En aplicaciones de Django, el usuario generalmente se obtiene a partir de la solicitud. Esta es la razón, la mayoría de las veces, los permisos se aplica en la capa de vista.

Por ejemplo, para evitar que un usuario sin permisos de vista en el modelo de usuario de acceder a una vista de que la información shows usuario, hacer lo siguiente:

from django.core.exceptions import PermissionDenied

def users_list_view(request):
if not request.user.has_perm('auth.view_user'):
raise PermissionDenied()

Si el usuario que realiza la solicitud conectado y fue autenticado, entonces request.user llevará a cabo una instancia de usuario. Si el usuario no inicio de sesión, a continuación, request.user será una instancia de AnonymousUser. Este es un objeto especial que se utiliza por Django para indicar un usuario no autenticado. Usando has_perm en AnonymousUser siempre devolverá False.

Si el usuario que realiza la solicitud no tiene el permiso view_user, entonces provocará una excepción PermissionDenied, y con una respuesta de estado 403 se devuelve al cliente.

Para que sea más fácil hacer cumplir los permisos en las vistas, Django provee un decorador de acceso directo llamado permission_required que hace la misma cosa:

from django.contrib.auth.decorators import permission_required

@permission_required('auth.view_user')
def users_list_view(request):
pass

Para aplicar los permisos en las plantillas, puede acceder a las actuales permisos de usuario a través de una variable de plantilla especial llamado permanentes. Por ejemplo, si desea mostrar un botón de eliminar sólo a los usuarios con permiso de eliminación, a continuación, haga lo siguiente:

{% if perms.auth.delete_user %}

{% endif %}

Algunos terceros populares aplicaciones como el marco resto de Django también proporcionan la integración útil con Django permisos modelo.

Django Admin y modelo de permisos

Django administrador tiene una integración muy estrecha con la incorporada en el sistema de autenticación y permisos modelo en particular. Fuera de la caja, Django de administración es la aplicación de permisos modelo:

  • Si el usuario no tiene permisos en un modelo, entonces no van a ser capaces de ver o acceder a él en el admin.
  • Si el usuario tiene ver y cambiar permisos en un modelo, entonces será capaz de ver y actualización de los casos, pero no será capaz de añadir nuevas instancias o eliminar los existentes.

Con los permisos adecuados en su lugar, los usuarios administradores tienen menos probabilidades de cometer errores, y los intrusos tendrá más dificultades para causar daño.

Implementar los roles de negocio personalizado en Django administración

Uno de los lugares más vulnerables de cada aplicación es el sistema de autenticación. En aplicaciones de Django, este es el modelo del usuario. Por lo tanto, para proteger mejor su aplicación, que se va a comenzar con el modelo de usuario.

En primer lugar, tiene que tomar el control de la página de administración modelo de usuario. Django ya viene con una página de administración muy agradable para administrar usuarios. Para aprovechar las ventajas de esa gran obra, que se va a extender la incorporada en el modelo de administración del usuario.

de configuración: usuario una administración

Para proporcionar un administrador de la medida para el modelo de usuario, es necesario anular el registro del administrador modelo existente proporcionada por Django, y se registra una propia:

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

# Unregister the provided model admin
admin.site.unregister(User)

# Register out own model admin, based on the default UserAdmin
@admin.register(User)
class CustomUserAdmin(UserAdmin):
pass

Su CustomUserAdmin está extendiendo UserAdmin de Django. Lo has hecho para que pueda tomar ventaja de todo el trabajo ya realizado por los desarrolladores de Django.

En este punto, si se acceda a su administración de Django en http://127.0.0.1:8000/admin/auth/user, usted debe ver el usuario admin sin cambios:

Al extender UserAdmin, que son capaces utilizar todas las funciones integradas de administración proporcionados por Django.

Prevenir la actualización de las formas de administración campos

desatendidas son un candidato ideal para errores horribles. Un usuario personal puede actualizar fácilmente una instancia de modelo a través del administrador de manera que la aplicación no espera. La mayoría de las veces, el usuario ni siquiera notarán que algo está mal. Tales errores son por lo general muy difícil de localizar y corregir.

Para evitar este tipo de errores del suceso, se puede evitar que los usuarios administradores modificar cierto campo en el modelo.

Si desea evitar que cualquier usuario, incluyendo los superusuarios, desde la actualización de un campo, puede marcar el campo como de sólo lectura. Por ejemplo, el campo date_joined se establece cuando un usuario se registra. Esta información nunca debe ser cambiado por cualquier usuario, por lo que lo marca como de sólo lectura:

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
readonly_fields = [
'date_joined',
]

Cuando se añade un campo para readonly_fields, no será editable en el formulario de cambio predeterminado de administración. Cuando un campo está marcado como de sólo lectura, Django hará que el elemento de entrada como discapacitados.

Pero, ¿y si desea evitar que sólo algunos usuarios de la actualización de un campo?

condicionalmente Prevenir la actualización de campos

A veces es útil para actualizar campos directamente en el admin. Pero usted no quiere dejar que cualquier usuario de hacerlo: desea permitir sólo superusuarios para hacerlo. de

Digamos que desea evitar que los no superusuarios de cambio de nombre de usuario de un usuario. Para ello, es necesario modificar el formulario de cambio generada por Django, y desactivar el campo nombre de usuario basado en el usuario actual: Rotura de

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs)
is_superuser = request.user.is_superuser

if not is_superuser:
form.base_fields['username'].disabled = True

return form

lo bajó:

  • para realizar ajustes en el formulario, se anula get_form (). Esta función es utilizada por Django para generar un formulario de cambio predeterminado para un modelo.
  • Para desactivar condicionalmente el campo, primero buscar el formulario predeterminado generado por Django y, a continuación, si el usuario no es un superusuario, desactivar el campo de nombre de usuario.

Ahora, cuando un no-superusuario intenta editar un usuario, se desactivará el campo nombre de usuario. Cualquier intento de modificar el nombre de usuario a través de Django administración fallará. Cuando un superusuario intentos para editar el usuario, el campo nombre de usuario será editable y se comportan como se esperaba.

impedir que los no superusuarios de conceder derechos de superusuario

superusuario es un permiso muy fuerte que no debe concederse a la ligera. Sin embargo, cualquier usuario con un permiso de modificación en el modelo de usuario puede hacer cualquier usuario un superusuario, incluidos ellos mismos. Esto va en contra de todo el propósito del sistema de permisos, por lo que desea cerrar este agujero.

basada en el ejemplo anterior, para evitar que los no superusuarios pretendan hacerse superusuarios, se agrega la restricción siguiente:

from typing import Set

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs)
is_superuser = request.user.is_superuser
disabled_fields = set() # type: Set[str]

if not is_superuser:
disabled_fields |= {
'username',
'is_superuser',
}

for f in disabled_fields:
if f in form.base_fields:
form.base_fields[f].disabled = True

return form

Además del ejemplo anterior, que hizo las siguientes adiciones:

ha inicializado un vacío disabled_fields escenografía que te mantener los campos a desactivar. conjunto es una estructura de datos que contiene valores únicos. Tiene sentido utilizar un conjunto en este caso, ya que sólo tiene que desactivar un campo de una vez. El operador | = se utiliza para realizar una actualización in situ o actualizar. Para obtener más información acerca de los conjuntos, echa un vistazo a conjuntos en Python.

A continuación, si el usuario es un superusuario, añadir dos campos al conjunto (nombre de usuario del ejemplo anterior, y is_superuser). Se evitarán los no superusuarios pretendan hacerse superusuarios.

Por último, iterar sobre los campos en el conjunto, marcan todos ellos como personas con discapacidad, y devolver el formulario.

Django Admin User dos pasos Formulario

Cuando se crea un nuevo usuario en Django administrador, ir a través de un formulario de dos pasos. En la primera forma, rellenar el nombre de usuario y contraseña. En la segunda forma, se actualiza el resto de los campos.

Este proceso de dos etapas es único para el modelo de usuario. Para adaptarse a este proceso único, debe comprobar que existe el campo antes de intentar desactivarlo. De lo contrario, es posible obtener un KeyError. Esto no es necesario si se personaliza otros administradores modelo.

Para obtener más información acerca de KeyError, echa un vistazo a excepciones Python KeyError y cómo manejarlos.

Conceder permisos Sólo Uso de grupos

La forma permisos se gestionan es muy específico para cada equipo, el producto y la empresa. He encontrado que es más fácil de administrar los permisos en grupos. En mis propios proyectos, puedo crear grupos de apoyo, los editores de contenido, analistas, y así sucesivamente. He descubierto que la administración de permisos a nivel de usuario puede ser una verdadera molestia. Cuando se añaden nuevos modelos, o cuando cambian los requerimientos del negocio, es tedioso para actualizar cada usuario individual.

Para administrar sólo permisos usando grupos, es necesario evitar que los usuarios la concesión de permisos a usuarios específicos. En su lugar, desea permitir sólo la asociación de usuarios a grupos. Para hacer eso, desactivar los user_permissions de campo para todos los no superusuarios:

from typing import Set

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs)
is_superuser = request.user.is_superuser
disabled_fields = set() # type: Set[str]

if not is_superuser:
disabled_fields |= {
'username',
'is_superuser',
'user_permissions',
}

for f in disabled_fields:
if f in form.base_fields:
form.base_fields[f].disabled = True

return form

ha utilizado la exacta misma técnica que en las secciones anteriores para aplicar otra regla de negocio. En las siguientes secciones, se va a poner en práctica las reglas de negocio más complejos para proteger su sistema.

impedir que los no superusuarios editen sus propios usuarios fuertes Permisos

son a menudo un punto débil. Ellos poseen permisos fuertes, y el daño potencial que puede causar es significativo. Para prevenir la escalada permiso en caso de intrusión, puede impedir que los usuarios editar sus propios permisos:

from typing import Set

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super().get_form(request, obj, **kwargs)
is_superuser = request.user.is_superuser
disabled_fields = set() # type: Set[str]

if not is_superuser:
disabled_fields |= {
'username',
'is_superuser',
'user_permissions',
}

# Prevent non-superusers from editing their own permissions
if (
not is_superuser
and obj is not None
and obj == request.user
):
disabled_fields |= {
'is_staff',
'is_superuser',
'groups',
'user_permissions',
}

for f in disabled_fields:
if f in form.base_fields:
form.base_fields[f].disabled = True

return form

El argumento obj es la instancia del objeto que se está operando actualmente en:

  • Cuando obj es Ninguno, el formulario se utiliza para crear un nuevo usuario.
  • Cuando obj no es Ninguno, el formulario se utiliza para modificar un usuario existente.

Para comprobar si el usuario que realiza la solicitud está operando en sí mismos, se compara con request.user obj. Debido a que este es el administrador de usuario, obj es ya sea una instancia de usuario o Ninguno. Cuando el usuario que realiza la solicitud, request.user, es igual a obj, entonces significa que el usuario está actualizando a sí mismos. En este caso, se deshabilita todos los campos sensibles que se pueden utilizar para obtener los permisos.

La capacidad de personalizar la forma en función del objeto es muy útil. Se puede utilizar para implementar las funciones de negocio elaborados.

Override Permisos

A veces puede ser útil para anular completamente los permisos en Django de administración. Un escenario común es cuando se utiliza permisos en otros lugares, y no desea que los usuarios de personal para hacer cambios en la administración.

Django usa ganchos para los cuatro incorporado permisos. Internamente, los ganchos usan los permisos del usuario actual para tomar una decisión. Se puede anular estos ganchos, y proporcionar una decisión diferente. usuarios del personal

para evitar que la supresión de una instancia de modelo, independientemente de sus permisos, puede hacer lo siguiente:

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
def has_delete_permission(self, request, obj=None):
return False

Al igual que con get_form (), obj es la instancia que opera actualmente en:

  • Cuando obj es Ninguno, el usuario solicitó la vista de lista.
  • Cuando obj no hay ninguno, el usuario solicitó la vista cambio de una instancia específica.

Tener la instancia del objeto en este gancho es muy útil para la aplicación de permisos a nivel de objeto para diferentes tipos de acciones. Aquí hay otros casos de uso:

  • La prevención de los cambios durante el horario comercial
  • ejecución permisos a nivel de objeto

restringir el acceso a las acciones de administración de acciones personalizadas

personalizadas requieren una atención especial. Django no está familiarizado con ellos, por lo que no se puede restringir el acceso a ellos de forma predeterminada. Una acción personalizada será accesible a cualquier usuario admin con ningún permiso para el modelo.

Para ilustrar, añadir una acción de administración útil para marcar varios usuarios como activa:

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
actions = [
'activate_users',
]

def activate_users(self, request, queryset):
cnt = queryset.filter(is_active=False).update(is_active=True)
self.message_user(request, 'Activated {} users.'.format(cnt))
activate_users.short_description = 'Activate Users' # type: ignore

Utilizando esta acción, el personal de un usuario puede marcar uno o más usuarios, y todos ellos activan a la vez. Esto es útil en todo tipo de casos, tales como si hubiera un error en el proceso de registro y necesaria para los usuarios activan a granel.

Esta acción actualiza la información del usuario, por lo que desea sólo los usuarios con permisos de cambio para poder utilizarlo.

Django de administración utiliza una función interna para conseguir acciones. Para ocultar activate_users () de los usuarios sin permiso de modificación, anulación get_actions (): get_actions

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

@admin.register(User)
class CustomUserAdmin(UserAdmin):
actions = [
'activate_users',
]

def activate_users(self, request, queryset):
assert request.user.has_perm('auth.change_user')
cnt = queryset.filter(is_active=False).update(is_active=True)
self.message_user(request, 'Activated {} users.'.format(cnt))
activate_users.short_description = 'Activate Users' # type: ignore

def get_actions(self, request):
actions = super().get_actions(request)
if not request.user.has_perm('auth.change_user'):
del actions['activate_users']
return actions

() devuelve una OrderedDict. La clave es el nombre de la acción, y el valor es la función de acción. Para ajustar el valor de retorno, se anula la función, ir a buscar el valor original, y en función de los permisos de usuario, eliminar los activate_users de acción personalizado desde el dict. Para estar en el lado seguro, usted afirma el permiso del usuario en la acción también.

Para los usuarios del personal sin change_user () permisos, los activate_users acción no aparecerá en el menú desplegable de acciones.

Conclusión

Django admin es una gran herramienta para la gestión de un proyecto de Django. Muchos equipos dependen de ella para mantener la productividad en la gestión de las operaciones del día a días. Si utiliza Django administrador para realizar operaciones en los modelos, entonces es importante ser consciente de permisos. Las técnicas descritas en este artículo son útiles para cualquier modelo de administración, no sólo el modelo de usuario.

En este tutorial, protegido su sistema al hacer los siguientes ajustes en Django admin:

  • te protegían contra la escalada de permiso de impedir a los usuarios editar sus propios permisos.
  • Usted mantiene permisos ordenada y fácil de mantener sólo obliga a los usuarios a administrar los permisos sólo se utilizan grupos.
  • le impidió permisos se filtre a través de acciones personalizadas de forma explícita mediante la aplicación de los permisos necesarios.

Su modelo de usuario de administración es ahora mucho más seguro que cuando comenzó!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *