在Django中定制身份验证

在Django中定制身份验证

Django附带的认证对于大多数常见情况来说已经足够了,但您可能需要通过开箱即用的默认设置才能满足需求。 要为您的项目定制身份验证,需要了解提供的系统的哪些点可扩展或可替换。

身份验证后端为用户模型存储的用户名和密码需要针对与Django默认不同的服务进行身份验证时提供了一个可扩展的系统。 您可以给您的模型定制可以通过Django的授权系统进行检查的权限。 您可以扩展默认的用户模型,或者替换完全自定义的模型。

其他验证来源

您可能有时需要挂接到另一个身份验证来源 - 也就是另一个用户名和密码来源或身份验证方法。

例如,您的公司可能已经有一个LDAP设置,为每个员工存储用户名和密码。如果用户在LDAP和基于Django的应用程序中有单独的帐户,那么对网络管理员和用户本身来说都是一件麻烦事。

所以,为了处理这样的情况,Django认证系统可以让你插入其他认证源。您可以重写Django的默认基于数据库的方案,或者可以与其他系统一起使用默认系统。

指定认证后端

在幕后,Django维护一个验证后端列表,它检查身份验证。当有人调用authenticate()时(正如前一节中介绍的有关登录用户的内容),Django会尝试在其所有身份验证后端进行身份验证。如果第一种认证方法失败,
Django尝试第二个,等等,直到所有的后端尝试。

在AUTHENTICATION_BACKENDS设置中指定要使用的身份验证后端列表。 这应该是一个Python路径名列表,指向知道如何进行身份验证的Python类。 这些类可以在你的Python路径上的任何地方。 默认情况下,AUTHENTICATION_BACKENDS
被设定为:

[‘django.contrib.auth.backends.ModelBackend‘]

这是检查Django用户数据库并查询内置权限的基本身份验证后端。它不提供通过任何速率限制机制防止暴力攻击的保护。您可以在自定义授权后端中实现您自己的速率限制机制,也可以使用大多数Web服务器提供的机制。 AUTHENTICATION_BACKENDS的顺序很重要,所以如果相同的用户名和密码在多个后端有效,Django将在第一次正面匹配时停止处理。如果后端引发PermissionDenied异常,认证将立即失败。 Django不会检查后面的后端。

一旦用户通过身份验证,Django就会存储哪些后端用于在用户会话中对用户进行身份验证,并在需要访问当前身份验证的用户时在该会话期间重新使用相同的后端。这实际上意味着每个会话都会缓存身份验证源,因此如果您更改AUTHENTICATION_BACKENDS,则需要清除会话数据(如果需要强制用户使用不同方法重新进行身份验证)。一个简单的方法就是执行Session.objects.all().delete()

编写身份验证后端

认证后端是一个实现两个必需方法的类:get_user(user_id)和authenticate(** credentials),以及一组可选的权限相关授权方法。 get_user方法需要一个user_id - 可以是一个用户名,数据库ID或其他,但必须是你的用户对象的主键 - 并返回一个用户对象。 身份验证方法将凭据作为关键字参数。 大多数情况下,它看起来像这样:

class MyBackend(object):
    def authenticate(self, username=None, password=None):
        # Check the username/password and return a User.
        ...

但它也可以验证令牌,如下所示:

class MyBackend(object):
    def authenticate(self, token=None):
        # Check the token and return a User.
        ...

无论哪种方式,身份验证都应该检查它获取的凭据,并且如果证书有效,它应该返回与这些凭证相匹配的用户对象。 如果它们无效,则应返回无。
Django管理系统与本章开头描述的Django用户对象紧密耦合。

现在,处理这个问题的最好方法是为每个存在于后端的用户创建一个Django User对象(例如,在您的LDAP目录,外部SQL数据库等中)。您可以编写脚本来执行此操作 或者您的身份验证方法可以在用户首次登录时执行此操作。

以下是一个示例后端,它会根据settings.py文件中定义的用户名和密码变量进行身份验证,并在用户首次进行身份验证时创建一个Django用户对象:

from django.conf import settings
from django.contrib.auth.models import User, check_password

class SettingsBackend(object):
    """
    Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.

    Use the login name, and a hash of the password. For example:

    ADMIN_LOGIN = ‘admin‘
    ADMIN_PASSWORD = ‘sha1$4e987$afbcf42e21bd417fb71db8c66b321e9fc33051de‘
    """

    def authenticate(self, username=None, password=None):
        login_valid = (settings.ADMIN_LOGIN == username)
        pwd_valid = check_password(password, settings.ADMIN_PASSWORD)
        if login_valid and pwd_valid:
            try:
                user = User.objects.get(username=username)
            except User.DoesNotExist:
                # Create a new user. Note that we can set password
                # to anything, because it won‘t be checked; the password
                # from settings.py will.
                user = User(username=username, password=‘password‘)
                user.is_staff = True
                user.is_superuser = True
                user.save()
            return user
        return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

处理自定义后端中的授权
自定义授权后端可以提供他们自己的权限。 用户模型会将权限查找函数(get_group_permissions(),get_all_permissions(),has_perm()和has_module_perms())委托给实现这些函数的任何验证后端。 赋予用户的权限将是所有后端返回的所有权限的超集。 也就是说,Django向任何一个后端授予的用户授予权限。

如果后端在has_perm()或has_module_perms()中引发PermissionDenied异常,授权将立即失败,Django将不检查后面的后端。 上面的简单后端可以简单地为管理员实现权限:

class SettingsBackend(object):
    ...
    def has_perm(self, user_obj, perm, obj=None):
        if user_obj.username == settings.ADMIN_LOGIN:
            return True
        else:
            return False

这给上面例子中授予访问权限的用户提供了完全的权限。 请注意,除了给予相关用户功能的相同参数之外,后端授权功能都将用户对象(可能是匿名用户)作为参数。

完整的授权实现可以在django / contrib / auth / backends.py中的ModelBackend类中找到,它是默认的后端,它大部分时间都会查询auth_permission表。 如果您希望仅为后端API的一部分提供自定义行为,则可以利用Python继承和子类ModelBackend,而不是在自定义后端中实现完整的API。

匿名用户授权

匿名用户是未经过身份验证的用户,即他们未提供有效的身份验证详细信息。 但是,这并不一定意味着他们无权做任何事情。 在最基本的层面上,大多数网站授权匿名用户浏览大部分网站,并且许多网站允许匿名发布评论等。

Django的权限框架没有地方为匿名用户存储权限。 但是,传递给身份验证后端的用户对象可能是django.contrib.auth.models.AnonymousUser对象,允许后端为匿名用户指定自定义授权行为。

这对于可重用应用程序的作者特别有用,他们可以将授权的所有问题委托给auth后端,而不需要设置,例如控制匿名访问。

对非活跃用户授权

非活跃用户是经过身份验证的用户,但其属性is_active设置为False。 但是,这并不意味着他们无权做任何事情。 例如,他们被允许激活他们的帐户。

对权限系统中的匿名用户的支持允许匿名用户有权执行某些操作,而不活动的经过身份验证的用户则不能这样做。 不要忘记在你自己的后端权限方法中测试用户的is_active属性。

处理对象权限

Django的权限框架为对象权限奠定了基础,但核心中没有实现它。 这意味着检查对象权限将始终返回False或一个空列表(取决于执行的检查)。 身份验证后端将为每个对象相关的授权方法接收关键字参数obj和user_obj,并可以根据需要返回对象级别权限。

自定义权限

要为给定的模型对象创建自定义权限,请使用权限模型元属性。 本示例任务模型创建三个自定义权限,即用户可以使用或不能使用Task实例执行的操作,具体针对您的应用程序:

class Task(models.Model):
    ...
    class Meta:
        permissions = (
            ("view_task", "Can see available tasks"),
            ("change_task_status", "Can change the status of tasks"),
            ("close_task", "Can remove a task by setting its status as
              closed"),
        )

这样做的唯一方法是在运行manage.py迁移时创建这些额外的权限。 当用户试图访问应用程序提供的功能(查看任务,更改任务状态,关闭任务)时,您的代码负责检查这些权限的值。继续上面的示例,以下示例将检查用户 可能会查看任务:

user.has_perm(‘app.view_task‘)
扩展现有的用户模型

有两种方法可以扩展默认用户模型,而不用替换自己的模型。 如果您需要的更改是纯粹的行为,并且不需要对存储在数据库中的内容进行任何更改,则可以基于用户创建代理模型。 这允许代理模型提供的任何功能,包括默认排序,自定义管理器或自定义模型方法。

如果您希望存储与用户相关的信息,则可以使用包含字段的模型的一对一关系以获取更多信息。 这种一对一模式通常称为配置文件模型,因为它可能存储有关站点用户的非auth相关信息。 例如,您可以创建一个Employee模型:

from django.contrib.auth.models import User

class Employee(models.Model):
   user = models.OneToOneField(User)
   department = models.CharField(max_length=100)

假设现有员工Fred Smith拥有User和Employee模型,则可以使用Django的标准相关模型约定访问相关信息:

>>> u = User.objects.get(username=‘fsmith‘)
>>> freds_department = u.employee.department

要将配置文件模型的字段添加到admin的用户页面,请在应用程序的admin.py中定义InlineModelAdmin(对于本示例,我们将使用StackedInline),并将其添加到UserAdmin类,该类用User类注册:

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

from my_user_profile_app.models import Employee

# Define an inline admin descriptor for Employee model
# which acts a bit like a singleton
class EmployeeInline(admin.StackedInline):
    model = Employee
    can_delete = False
    verbose_name_plural = ‘employee‘

# Define a new User admin
class UserAdmin(UserAdmin):
    inlines = (EmployeeInline, )

# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)

这些配置文件模型在任何方面都不是特别的 - 它们只是恰好与用户模型具有一对一链接的Django模型。因此,创建用户时不会自动创建,但可以根据需要使用django.db.models.signals.post_save创建或更新相关模型。

请注意,使用相关模型会产生额外的查询或连接以检索相关数据,根据您的需要,替换用户模型并添加相关字段可能是更好的选择。但是,项目应用程序中默认用户模型的现有链接可能会导致额外的数据库负载。

代替自定义用户模型

某些类型的项目可能具有身份验证要求,因此Django的内置User模型并不总是适合的。例如,在一些网站上,使用电子邮件地址作为您的身份标记而不是用户名更有意义。 Django允许您通过为引用自定义模型的AUTH_USER_MODEL设置提供值来覆盖默认的用户模型:

`AUTH_USER_MODEL = ‘books.MyUser‘`

此虚线对描述了Django应用程序的名称(它必须位于INSTALLED_APPS中),以及您希望用作用户模型的Django模型的名称。

改变AUTH_USER_MODEL对你的Django项目有很大的影响,特别是你的数据库结构。 例如,如果在运行迁移后更改AUTH_USER_MODEL,则必须手动更新数据库,因为它会影响许多数据库表关系的构建。 除非有充分理由这样做,否则不应更改AUTH_USER_MODEL。

尽管有上述警告,但Django完全支持自定义用户模型,但完整的解释超出了本书的范围。 Django项目网站上提供了一个完全符合管理员要求的自定义用户应用程序示例,以及有关自定义用户模型的全面文档。

转载自:https://www.jianshu.com/p/5806ff9c0cc5

原文地址:https://www.cnblogs.com/cyberworld/p/9830982.html

时间: 2024-11-05 19:38:28

在Django中定制身份验证的相关文章

nancy中的身份验证

在nancy中,身份验证分为basic ,form ,token,stateless几种,basic和form这里不说了,其中如果是使用cookie来保存身份的, 需要注意的是:cookie有大小的限制,所以不能用来保存超过4k的信息,而且有一些js插件也要用的cookie,虽然html5好像多了.但是还是要注意一下.因为之前看到文章有的人网站有时候登陆出现问题,就是因为用户信息太大导致的. 这里说的是token的验证. ITokenizer 这个是定义token的接口,Tokenizer是它的

用Retrofit发送请求中添加身份验证

用Retrofit发送请求中添加身份验证====================在安卓应用开发中, retrofit可以极大的方便发送http网络请求,不管是GET, POST, 还是PUT, DELETE, Retrofit使用起来都非常简单.只要稍微看一下文档,就知道怎么用.但文档没有具体说明怎么怎么发送带auth信息的请求.本文分享两个代码片段. 比如要发送这样的请求,在header中添加身份验证信息,用户名和密码: http -a user1:user1password POST htt

sqlserver 2012 IDE中 Windows身份验证连接服务器报错 ,Login failed for user 'xxx\Administrator'. 原因: 找不到与提供的名称匹配的登录名。

问题描述: 本地装了两个实例,一个是SQLEXPRESS,可以正常操作.但是另一个开发常用的实例MSSQLSERVER却连Windows身份验证都报错,报的错误也是很奇葩,怎么会找不到Administrator那,我登录计算机进来就用的这个账号. 详细错误如下: 无法连接到 xxx.===================================用户 'xxx\Administrator' 登录失败. (.Net SqlClient Data Provider)--------------

AngularJS中的身份验证

欢迎大家指导与讨论 : )  一.  身份验证的意义    首先呢,网络应用的身份验证的意图在于:保护网站中的重要资源.基于某些原因这些资源并不能公开,比如付费资源(交过钱的用户才能上的网络课程),或者一些管理功能.  二. 1. 客户端身份验证——保护API访问资源  二. 2. 客户端身份验证——使用路由定义受保护资源 首先我们需要四样工具.1. angular常量constant. 2. $routerProvider配置为每个路由配置权限. 3. 创建一个能操作cookie并判断是否有权

sql server 2008 windows验证改混合登陆中SqlServer身份验证用户名密码

安装过程中,SQL Server 数据库引擎设置为 Windows 身份验证模式或 SQL Server 和 Windows 身份验证模式.本主题介绍如何在安装后更改安全模式. 如果在安装过程中选择“Windows 身份验证模式”,则 sa 登录名将被禁用.如果稍后将身份验证模式更改为“SQL Server 和 Windows 身份验证模式”,则 sa 登录名仍处于禁用状态.若要启用 sa 登录帐户,请使用 ALTER LOGIN 语句. 安全说明: sa 帐户是一个广为人知的 SQL Serv

SQL Server中服务器身份验证及用户登录

安装过程中,SQL Server 数据库引擎设置为"Windows 身份验证模式"或"SQL Server 和 Windows 身份验证模式". 安装完成后,您可以随时更改身份验证模式. 如果在安装过程中选择了"Windows 身份验证模式",则 sa 登录名将被禁用,安装程序会分配一个密码. 如果稍后将身份验证模式更改为"SQL Server 和 Windows 身份验证模式",则 sa 登录名仍处于禁用状态. 若要使用 s

EXCHANGE客户端访问服务器(CAS)中的身份验证方式

在部署完毕exchange后系统会自动建立IIS服务来响应相应的请求.客户端访问服务器(以下简称CAS)实质上是一台IIS服务器,在服务器中部署一套名为"Default web site"的站点来完成OWA.ecp.activesync.outlookanywhere.autodiscover等应用的响应. tips:Default web site 站点对应的是CAS服务器角色Exchange back end 站点对应的是邮箱服务器角色 如果想改变身份验证方式,启动IIS管理器,找

ASP.NET中的身份验证有那些?你当前项目采用什么方式验证请解释

ASP.NET身份验证模式包括Windows.Forms(窗体).Passport(护照)和None(无). l  Windows身份验证—常结合应用程序自定义身份验证使用使用这种身份验证模式时,ASP.NET依赖于IIS对用户进行验证,并创建一个Windows访问令牌来表示已通过验证的标识.IIS提供以下几种身份验证机制: l  Passport身份验证.使用这种身份验证模式时,ASP.NET使用Microsoft Passport的集中式身份验证服务,该服务为成员站点提供单一登录和核心配置文

[小技巧][ASP.Net MVC Hack] 使用 HTTP 报文中的 Header 字段进行身份验证

在一些 Web 系统中,身份验证是依靠硬件证书进行的:在电脑上插入 USB 证书,浏览器插件读取证书的相关信息,然后在发送 HTTP 登录请求时顺便在 Header 字段附加上身份信息.服务器端处理这样的登录请求的思路也很简单,就是读取 HTTP Header 相关信息,然后进行相应的处理. 在 ASP.Net MVC 架构的网站中,自然也可以使用这样的机制,下面基于 Visual Studio 2012 演示一下操作步骤. 首先建立一个ASP.Net MVC 4 项目. 选择模板的时候,保留默