Django contrib auth authenticate函数源码解析

作者:codeLeaves 时间:2022-04-27 01:49:23 

引言

django提供了一个默认的auth系统用于用户的登录和授权,并提供了一定的扩展性,允许开发者自行定义多个验证后台,每个验证后台必须实现authenticate函数,并返回None或者User对象。

默认的后台是django.contrib.auth.backends.ModelBackend,该后台通过用户名和密码进行用户的验证,以settings.AUTH_USER_MODEL作为模型。但是在实际的开发中,相信大家都不会固定的使用用户名以及同一个model进行验证,比如,不同的角色需要不同的model作为验证的数据源,有的角色是使用手机登录,而有的角色使用邮箱登录。

那么,当存在多个验证后台的时候,django是如何制作一个统一的接口进行不同后台的验证呢?

authenticate函数分析

源码:


def authenticate(**credentials):
 """
 If the given credentials are valid, return a User object.
 """
 for backend, backend_path in _get_backends(return_tuples=True):
   try:
     inspect.getcallargs(backend.authenticate, **credentials)
   except TypeError:
     # This backend doesn't accept these credentials as arguments. Try the next one.
     continue

try:
     user = backend.authenticate(**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))

**credentials

首先可以看到authenticate函数接受的参数,这是指authenticate函数只接受关键字传参,位置传参是不允许的。因此在使用authenticate函数的时候注意不要为了省事而位置传参。

# This will fail
user = authenticate('username', 'password')

# This will success
user = authenticate(username='username', password='password')

inspect.getcallargs(func, *args, **kwargs)
inspect模块是Python官方的标准模块,这个模块对Python的自省功能进行一定的封装。其中inspect.getcallargs检查args和kwargs这些参数是否能被func要求的参数匹配,若匹配成功返回参数字典,如果不能匹配就会raise TypeError。
举个简单的例子。假设在Python中定义这样一个函数:


import inspect
def test_func(arg1, arg2, *args, **kwargs):
 pass
# this will raise TypeError
inspect.getcallargs(test_func, a=1, b=2, c=3)
# TypeError: test_func() missing 2 required positional arguments: 'arg1' and 'arg2'

# this will ok
inspect.getcallargs(test_func, 1, 2, 3, a=1, b=2, c=3)
# {'kwargs': {'b': 2, 'c': 3, 'a': 1}, 'arg2': 2, 'args': (3,), 'arg1': 1}

应用场景

通过inspect.getcallargs的参数过滤功能,只要设置不同后台的authenticate的函数参数,就能在第一步实现不同角色的后台选择。

假设有三种角色,角色1使用用户名登录,角色2使用手机登录,角色3使用手机或者邮箱登录,那么如何通过inspect.getcallargs就选择合适的backend.authenticate呢?


def role3_authenticate(role3_phone=None, role3_email=None, password=None):
 print("role1 authentication.")

def role2_authenticate(role2_phone=None, password=None):
 print("role2 authenticate.")

def role1_authenticate(role1_name=None, password=None):
 print("role2 authenticate.")

methods = [role1_authenticate, role2_authenticate, role3_authenticate]
def authenticate(**credentials):
 for backend in methods:
   try:
     inspect.getcallargs(backend, **credentials)
   except TypeError:
     print("error")
     continue

backend(**credentials)
   print("end")
   break

如果加入**kwargs则每个authenticate都不会引发TypeError,因为其余参数都设置了默认参数,如果确实需要,则之前的参数使用位置传参。

signal

若用户没有成功登陆,则authenticate发送了一个用户没有成功登陆的信号,开发者可以自行定义接受这个信号的recevier。关于django signal笔者之后还会详细谈及。

来源:https://blog.csdn.net/laughing2333/article/details/53041166

标签:Django,contrib,auth,authenticate
0
投稿

猜你喜欢

  • 基于tensorflow权重文件的解读

    2023-11-04 02:05:35
  • 记录Python脚本的运行日志的方法

    2022-09-25 08:11:12
  • 如何利用python和DOS获取wifi密码

    2021-12-15 20:10:50
  • JAVA正则表达式校验qq号码的方法

    2023-08-09 02:54:25
  • PHP PDOStatement::rowCount讲解

    2023-06-06 12:24:04
  • Python自动打印被调用函数变量名及对应值 

    2022-08-05 09:50:38
  • python画环形图的方法

    2023-02-12 09:54:24
  • Python绘制全球疫情变化地图的实例代码

    2022-08-27 07:06:46
  • 基于Python的文件类型和字符串详解

    2023-08-03 12:51:26
  • Python设计模式中的结构型桥接模式

    2021-07-23 23:43:31
  • Python使用pydub模块转换音频格式以及对音频进行剪辑

    2023-03-22 02:17:37
  • 解决Python一行输出不显示的问题

    2021-05-19 19:21:46
  • 用Python抢火车票的简单小程序实现解析

    2023-09-06 06:31:28
  • 对python3中pathlib库的Path类的使用详解

    2023-05-11 23:44:49
  • Python面向对象程序设计之类的定义与继承简单示例

    2022-03-24 03:00:16
  • TensorFlow数据输入的方法示例

    2022-04-27 03:32:03
  • 立足于传统行业设计

    2008-07-26 12:36:00
  • python单线程实现多个定时器示例

    2023-05-11 08:59:18
  • PHP strip_tags() 去字符串中的 HTML、XML 以及 PHP 标签的函数

    2023-06-09 01:05:00
  • IE7下 filter:Alpha(opacity=xx) 的小问题

    2008-12-02 16:24:00
  • asp之家 网络编程 m.aspxhome.com