什么是用户认证
用户认证后端位置:
django.contrib.auth.backends.ModelBackend
authenticate()有什么用
怎样使用
from django.contrib.auth import authenticate
user=authenticate(username=username,password)
自定义后端认证步骤:
个人认为它的好处,并且它的认证功能比较安全可靠:
在没有使用自带的认证的情况下,个人普通认证逻辑:
### 这里演示登录认证用户是否已注册
#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'