django authenticate--用户身份认证

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

authenticate
Django的contrib.auth模块中的authenticate()函数用于对用户的凭据进行身份验证与已配置的身份验证后端进行比较。

当用户尝试登录时authenticate()函数将使用用户的凭据即用户名和密码作为参数进行调用,该函数然后检查可用的身份验证后端以验证凭据这些后端在项目的settings.py文件中定义,如果凭据有效则authenticate()函数返回已认证的用户对象;否则它返回None。
在成功身份验证后可以使用Django的login()函数登录用户。

认证后端
1.AUTHENTICATION_BACKENDS是Django设置中的一个参数它定义了用于身份验证的后端认证方式。这个参数是一个字符串列表包含Django认证系统使用的认证后端类的全名。

2.当用户尝试进行身份验证时Django将按照AUTHENTICATION_BACKENDS中定义的顺序尝试每个后端认证方式直到找到一个认证方式成功为止。如果所有后端认证方式都失败则身份验证失败。

3.默认情况下Django使用ModelBackend作为身份验证后端它基于Django中的用户模型进行身份验证。除此之外Django还提供了其他的身份验证后端如LDAPBackend、RemoteUserBackend等也可以自定义身份验证后端。

4.通过配置AUTHENTICATION_BACKENDS参数可以对身份验证后端进行定制以满足具体项目的需求。例如如果你的项目需要使用LDAP进行用户身份验证则可以添加LDAPBackend到AUTHENTICATION_BACKENDS列表中以便Django使用LDAPBackend进行身份验证。

from django.contrib.auth import authenticate
from django.contrib.auth import login as user_login
def my_login(request):
    """
    登录视图
    :param request:
    :return:
    """
    if request.method == "POST":
        login_form = users_form.UserForm(request.POST)
        if login_form.is_valid():
            username = login_form.cleaned_data['username']
            password = login_form.cleaned_data['password']
            myuser = authenticate(username=username, password=password)
            if myuser is not None:
                user_login(request, myuser)

这段代码使用Django的contrib.auth模块来进行用户身份验证和登录。
首先它调用authenticate()函数验证用户的凭据,如果凭据有效则authenticate()函数将返回已认证的用户对象并将其赋给myuser变量。如果凭据无效则authenticate()函数将返回None。
接着代码检查myuser变量是否为None。如果myuser不为None则说明凭据有效并且代码将调用user_login()函数来将该用户登录到当前会话中。user_login()函数需要传递一个request对象和已认证的用户对象。登录成功后用户可以访问需要认证的页面和视图。
如果myuser为None则说明凭据无效用户无法登录。

myuser 和 request.user 是两个不同的对象其区别在于
1.myuser 表示通过用户名和密码认证成功后得到的用户对象 是通过表单验证之后从数据库中查询出来的用户对象即 authenticate 方法返回的对象。主要用来检查用户输入的用户名和密码是否正确并在认证成功后设置一些 session 变量。
2.request.user 表示当前请求的用户对象是通过 Django 的认证系统得到的用户对象包括通过认证的用户和未认证的用户。如果用户已通过认证则该对象是一个 User 实例否则是一个 AnonymousUser 实例。 主要用来获取当前认证的用户信息例如用户的用户名、邮箱等。这些信息通常用来显示在页面上或者用来判断当前用户是否有权限进行某些操作。

因此在这个方法中myuser 和 request.user 作用是相同的都是用来判断用户是否已通过认证但是可能是不同的对象因为 myuser 只在用户认证成功后才会有值而 request.user 则是在每个请求中都会有值不论用户是否通过认证。同时在这个方法中myuser 和 request.user 都可以用来检查用户是否已通过认证但是只有 request.user 才可以用来获取当前认证的用户信息。

authenticate函数如下:


@sensitive_variables("credentials")
def authenticate(request=None, **credentials):
    """
    If the given credentials are valid, return a User object.
    """
    for backend, backend_path in _get_backends(return_tuples=True):
        backend_signature = inspect.signature(backend.authenticate)
        try:
            backend_signature.bind(request, **credentials)
        except TypeError:
            # This backend doesn't accept these credentials as arguments. Try
            # the next one.
            continue
        try:
            user = backend.authenticate(request, **credentials)
        except PermissionDenied:
            # This backend says to stop in our tracks - this user should not be
            # allowed in at all.
            break
        if user is None:
            continue
        # Annotate the user object with the path of the backend.
        user.backend = backend_path
        return user

_get_backends会从settings.py中读取AUTHENTICATION_BACKENDS定义的后端路径

def _get_backends(return_tuples=False):
    backends = []
    for backend_path in settings.AUTHENTICATION_BACKENDS:
        backend = load_backend(backend_path)
        backends.append((backend, backend_path) if return_tuples else backend)
    if not backends:
        raise ImproperlyConfigured(
            "No authentication backends have been defined. Does "
            "AUTHENTICATION_BACKENDS contain anything?"
        )
    return backends
AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'backends.user_backend.UserBackend'
]

AUTHENTICATION_BACKENDS列表中包含了两个认证后端分别是ModelBackend和UserBackend。Django将按照列表中的顺序依次尝试这两个认证后端直到找到一个成功为止。

UserBackend需要继承BaseBackend并实现一个authenticate函数

from django.contrib.auth.backends import BaseBackend
from users.models import MyUser


class UserBackend(BaseBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            myuser = MyUser.objects.get(name=username)
            if myuser.check_password(password):
                return myuser
        except MyUser.DoesNotExist as e:
            print("user no exist", e)
            return None

    def get_user(self, user_id):
        try:
            return MyUser.objects.get(pk=user_id)
        except MyUser.DoesNotExist:
            return None
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: go