Django2.0 自带的用户认证系统authenticate()

authenticate()用户认证系统学习笔记

  • 什么是用户认证

    • 是Django自带的用户认证后端,默认是使用用户名实现用户认证
  • 用户认证后端位置:
    django.contrib.auth.backends.ModelBackend

  • authenticate()有什么用

    • 用于认证用户名是否存在数据库中;通常用于:登录认证
    • 还可以自定义用户认证:例如:使用用户名和手机号来认证用户
  • 怎样使用

    • 1、导入authenticate包:from django.contrib.auth import authenticate
    • 2、直接调用:
      	user=authenticate(username=username,password)
      
  • 自定义后端认证步骤:

    • 在user应用中创建lib.py文件
    • 在lib.py文件中创建一个类,并继承ModelBankend
    • 重写authenticate()方法
    • 分别使用用户名和手机号来查询用户
    • 返回查询到的用户实例
  • 个人认为它的好处,并且它的认证功能比较安全可靠:

    • 防止在验证过程中出现异常
    • 使用起来比普通认证逻辑要省时省事
  • 在没有使用自带的认证的情况下,个人普通认证逻辑:

    ### 这里演示登录认证用户是否已注册
    	#1、首先导入用户模型类包(根据自己的结构来导入)
    	#2、尝试从User模型类中连接用户表数据库
    try:
    	user=User.objects.get(username=username)
    except:
    	#3、如果抛出异常,则说明没有该用户名
    	return http.HttpResponseServerError("用户名或密码不正确")
    #4、如果能够查询出有该用户名,则校验用户的密码是否正确
    if  not user.check_password(password=password)
    	return http.HttpResponseServerError("用户名或密码不正确")
    else:
    	#5、验证都通过,则状态保持登录,使用Django自带的login()方法
    	from django.contrib.auth import login()
    	login(request,user)
    
    	#6、设置session的过期时间,因为login()使用的是cookie-session机制来进行做状态保持
    	#7、如果没有勾选记住密码,则在浏览器会话结束就删除该用户的session信息
    	if not allow:
    		request.session.set_expiry(0)	#使用request对象的session中的set_expiry()方法来实现,0:表示结束会话后立刻删除session信息
    	#8、如果有勾选记住密码,则在浏览器中设置一个保存session的时间
    	else:
    		request.session.set_expiry(None)	#None:表示会话结束后的2周时间后就删除session信息
    	
    	#9、登录成功后重定向到首页
    	return redirect('/')	
    
  • 使用Django自带的认证系统的情况下:

    #1、导入Django自带的authenticate方法
    from django.contrib.auth import login, authenticate
    #2、直接使用用户认证(这一步之前,需要提前校验前端传入过来的数据格式要求是否达标)
    user=authenticate(username=username,password=password)
    #3、如果认证失败就会返回None,认证成功就会返回User对象,则判断user是否为None,如果不是则 用户是以注册的用户。
    if user is None:
    	return http.HttpResponseServerError("用户名或密码不正确")
    else:
    #4、认证通过,则执行状态保持进行登录
    	login(request,user) 
    #5、判断是否记住密码,是记住则设置session信息,否则会话结束后就删除session信息
    	if not allow:
    		request.session.set_expiry(0)
    	else:
    		request.session.set_expiry(None)
    #6、登录成功,重定向到首页
    	return redirect('/')	
    
  • Source(源码)

	Django 2.0.14.dev20190701080343 documentation
Home | Table of contents | Index | Modules
up
Source code for django.contrib.auth
import inspect
import re
import warnings

from django.apps import apps as django_apps
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.middleware.csrf import rotate_token
from django.utils.crypto import constant_time_compare
from django.utils.deprecation import RemovedInDjango21Warning
from django.utils.module_loading import import_string
from django.utils.translation import LANGUAGE_SESSION_KEY

from .signals import user_logged_in, user_logged_out, user_login_failed

SESSION_KEY = '_auth_user_id'
BACKEND_SESSION_KEY = '_auth_user_backend'
HASH_SESSION_KEY = '_auth_user_hash'
REDIRECT_FIELD_NAME = 'next'


def load_backend(path):
	#加载认证后端的配置文件路径
    return import_string(path)()


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


def get_backends():
    return _get_backends(return_tuples=False)


def _clean_credentials(credentials):
    """
    Clean a dictionary of credentials of potentially sensitive info before
    sending to less secure functions.

    Not comprehensive - intended for user_login_failed signal
    """
    SENSITIVE_CREDENTIALS = re.compile('api|token|key|secret|password|signature', re.I)
    CLEANSED_SUBSTITUTE = '********************'
    for key in credentials:
        if SENSITIVE_CREDENTIALS.search(key):
            credentials[key] = CLEANSED_SUBSTITUTE
    return credentials


def _get_user_session_key(request):
    # This value in the session is always serialized to a string, so we need
    # to convert it back to Python whenever we access it.
    return get_user_model()._meta.pk.to_python(request.session[SESSION_KEY])


def authenticate(request=None, **credentials):
    """
    If the given credentials are valid, return a User object.传入关键字参数并传给**credentials校验数据
    """
    for backend, backend_path in _get_backends(return_tuples=True):
        try:
            user = _authenticate_with_backend(backend, backend_path, 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

    # The credentials supplied are invalid to all backends, fire signal
    user_login_failed.send(sender=__name__, credentials=_clean_credentials(credentials), request=request)


def _authenticate_with_backend(backend, backend_path, request, credentials):
    args = (request,)
    # Does the backend accept a request argument?
    try:
        inspect.getcallargs(backend.authenticate, request, **credentials)
    except TypeError:
        args = ()
        credentials.pop('request', None)
        # Does the backend accept a request keyword argument?
        try:
            inspect.getcallargs(backend.authenticate, request=request, **credentials)
        except TypeError:
            # Does the backend accept credentials without request?
            try:
                inspect.getcallargs(backend.authenticate, **credentials)
            except TypeError:
                # This backend doesn't accept these credentials as arguments. Try the next one.
                return None
            else:
                warnings.warn(
                    "Update %s.authenticate() to accept a positional "
                    "`request` argument." % backend_path,
                    RemovedInDjango21Warning
                )
        else:
            credentials['request'] = request
            warnings.warn(
                "In %s.authenticate(), move the `request` keyword argument "
                "to the first positional argument." % backend_path,
                RemovedInDjango21Warning
            )
    return backend.authenticate(*args, **credentials)





def logout(request):
    """
    Remove the authenticated user's ID from the request and flush their session
    data.
    """
    # Dispatch the signal before the user is logged out so the receivers have a
    # chance to find out *who* logged out.
    user = getattr(request, 'user', None)
    if hasattr(user, 'is_authenticated') and not user.is_authenticated:
        user = None
    user_logged_out.send(sender=user.__class__, request=request, user=user)

    # remember language choice saved to session
    language = request.session.get(LANGUAGE_SESSION_KEY)

    request.session.flush()

    if language is not None:
        request.session[LANGUAGE_SESSION_KEY] = language

    if hasattr(request, 'user'):
        from django.contrib.auth.models import AnonymousUser
        request.user = AnonymousUser()


def get_user_model():
    """
    Return the User model that is active in this project.
    """
    try:
        return django_apps.get_model(settings.AUTH_USER_MODEL, require_ready=False)
    except ValueError:
        raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form 'app_label.model_name'")
    except LookupError:
        raise ImproperlyConfigured(
            "AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL
        )




def get_permission_codename(action, opts):
    """
    Return the codename of the permission for the specified action.
    """
    return '%s_%s' % (action, opts.model_name)


def update_session_auth_hash(request, user):
    """
    Updating a user's password logs out all sessions for the user.

    Take the current request and the updated user object from which the new
    session hash will be derived and update the session hash appropriately to
    prevent a password change from logging out the session from which the
    password was changed.
    """
    request.session.cycle_key()
    if hasattr(user, 'get_session_auth_hash') and request.user == user:
        request.session[HASH_SESSION_KEY] = user.get_session_auth_hash()


default_app_config = 'django.contrib.auth.apps.AuthConfig'

还有很多知识还没弄懂,先暂时这样,如果有那些地方错了的遗漏的地方,请大神指点

你可能感兴趣的:(Django2.0 自带的用户认证系统authenticate())