博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
django.contrib.auth登陆注销学习
阅读量:6138 次
发布时间:2019-06-21

本文共 10568 字,大约阅读时间需要 35 分钟。

hot3.png

auth模块实现功能

通过入口url.py文件中定义的urlpatterns可以看出,auth模块共定义了8个url,分别用于:

  • 登录
  • 注销
  • 修改密码
  • 修改密码完成
  • 密码重置
  • 密码重置完成
  • 密码重置验证
  • 密码重置结束
from django.conf.urls import urlfrom django.contrib.auth import views# urlpatterns直接是一个list即可urlpatterns = [    url(r'^login/$', views.login, name='login'),    url(r'^logout/$', views.logout, name='logout'),    url(r'^password_change/$', views.password_change, name='password_change'),    url(r'^password_change/done/$', views.password_change_done, name='password_change_done'),    url(r'^password_reset/$', views.password_reset, name='password_reset'),    url(r'^password_reset/done/$', views.password_reset_done, name='password_reset_done'),    url(r'^reset/(?P
[0-9A-Za-z_\-]+)/(?P
[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', views.password_reset_confirm, name='password_reset_confirm'), url(r'^reset/done/$', views.password_reset_complete, name='password_reset_complete'),]

这篇文章主要学习登录和注销相关代码

login 登录

def login(request, template_name='registration/login.html',          redirect_field_name=REDIRECT_FIELD_NAME,          authentication_form=AuthenticationForm,          extra_context=None):    """    Displays the login form and handles the login action.    """    redirect_to = request.POST.get(redirect_field_name,                                   request.GET.get(redirect_field_name, ''))    if request.method == "POST":        form = authentication_form(request, data=request.POST)        if form.is_valid():            # Ensure the user-originating redirection url is safe.            if not is_safe_url(url=redirect_to, host=request.get_host()):                redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)            # Okay, security check complete. Log the user in.            auth_login(request, form.get_user())            return HttpResponseRedirect(redirect_to)    else:        form = authentication_form(request)    current_site = get_current_site(request)    context = {        'form': form,        redirect_field_name: redirect_to,        'site': current_site,        'site_name': current_site.name,    }    if extra_context is not None:        context.update(extra_context)    return TemplateResponse(request, template_name, context)

登录处理视图函数依据功能分为:

  • 展示登录页面供用户提供认证信息进行登录操作(request.method == "GET")
  • 对用户提交的认证信息进行认证,并做出相应反映(request.method == "POST")

request.method == "GET"

  1. 实例化一个authentication_form实例(通过传入request将request绑定到form实例上),供用户输入认证信息
  2. 获取站点信息,供页面显示
  3. 生成context,并使用关键词参数extra_context进行拓展
  4. 返回页面(TemplateResponse)

此场景处理逻辑较简单

request.method == "POST"

  1. 通过获取到的用户数据(request.POST)实例化authentication_form
  2. 判断用户输入数据是否有效合理(检查是否有输入传入;并且调用full_clean方法来进行验证)。默认的AuthenticationForm中的clean方法中会调用django.contrib.auth.authenticate方法对用户提供的认证信息进行校验。而authenticate方法会遍历settings中定义的AUTHENTICATION_BACKENDS模块,并调用模块的authenticate方法进行认证,直到成功,否则出发user_login_failed singnal
  3. 调用django.contrib.auth.login方法使得用户登录成功,并返回HttpResponseRedirect响应,重定向到redirect_field_name指向地址。
step2 form.is_valid()调用过程# django.forms.forms.pyclass BaseForm(object):    ....    @property    def errors(self):        "Returns an ErrorDict for the data provided for the form"        if self._errors is None:            self.full_clean()        return self._errors    def is_valid(self):        """        Returns True if the form has no errors. Otherwise, False. If errors are        being ignored, returns False.        """        return self.is_bound and not self.errors        def full_clean(self):        """        Cleans all of self.data and populates self._errors and        self.cleaned_data.        """        self._errors = ErrorDict()        if not self.is_bound:  # Stop further processing.            return        self.cleaned_data = {}        # If the form is permitted to be empty, and none of the form data has        # changed from the initial data, short circuit any validation.        if self.empty_permitted and not self.has_changed():            return        self._clean_fields()        self._clean_form()        self._post_clean()            def _clean_fields(self):        for name, field in self.fields.items():            # value_from_datadict() gets the data from the data dictionaries.            # Each widget type knows how to retrieve its own data, because some            # widgets split data over several HTML fields.            if field.disabled:                value = self.initial.get(name, field.initial)            else:                value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))            try:                if isinstance(field, FileField):                    initial = self.initial.get(name, field.initial)                    value = field.clean(value, initial)                else:                    value = field.clean(value)                self.cleaned_data[name] = value                ## 如果有clean_filedname方法的话,调用之                if hasattr(self, 'clean_%s' % name):                    value = getattr(self, 'clean_%s' % name)()                    self.cleaned_data[name] = value            except ValidationError as e:                self.add_error(name, e)    def _clean_form(self):        try:            cleaned_data = self.clean()        except ValidationError as e:            self.add_error(None, e)        else:            if cleaned_data is not None:                self.cleaned_data = cleaned_data    def _post_clean(self):        """        An internal hook for performing additional cleaning after form cleaning        is complete. Used for model validation in model forms.        """        pass
step2 django.contrib.auth.authenticate方法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 backendsdef 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.            return None        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))
step3 django.contrib.auth.login方法1. request.user = user2. 触发user_logged_in singnaldef login(request, user):    """    Persist a user id and a backend in the request. This way a user doesn't    have to reauthenticate on every request. Note that data set during    the anonymous session is retained when the user logs in.    """    session_auth_hash = ''    if user is None:        user = request.user    if hasattr(user, 'get_session_auth_hash'):        session_auth_hash = user.get_session_auth_hash()    if SESSION_KEY in request.session:        if _get_user_session_key(request) != user.pk or (                session_auth_hash and                request.session.get(HASH_SESSION_KEY) != session_auth_hash):            # To avoid reusing another user's session, create a new, empty            # session if the existing session corresponds to a different            # authenticated user.            request.session.flush()    else:        request.session.cycle_key()    request.session[SESSION_KEY] = user._meta.pk.value_to_string(user)    request.session[BACKEND_SESSION_KEY] = user.backend    request.session[HASH_SESSION_KEY] = session_auth_hash    if hasattr(request, 'user'):        request.user = user    rotate_token(request)    user_logged_in.send(sender=user.__class__, request=request, user=user)

logout 注销

@deprecate_current_appdef logout(request, next_page=None,           template_name='registration/logged_out.html',           redirect_field_name=REDIRECT_FIELD_NAME,           extra_context=None):    """    Logs out the user and displays 'You are logged out' message.    """    auth_logout(request)    if next_page is not None:        next_page = resolve_url(next_page)    if (redirect_field_name in request.POST or            redirect_field_name in request.GET):        next_page = request.POST.get(redirect_field_name,                                     request.GET.get(redirect_field_name))        # Security check -- don't allow redirection to a different host.        if not is_safe_url(url=next_page, host=request.get_host()):            next_page = request.path    if next_page:        # Redirect to this page until the session has been cleared.        return HttpResponseRedirect(next_page)    current_site = get_current_site(request)    context = {        'site': current_site,        'site_name': current_site.name,        'title': _('Logged out')    }    if extra_context is not None:        context.update(extra_context)    return TemplateResponse(request, template_name, context)

实现了登出用户,并跳转到指定(next_page或者request.GET, request.POST中携带的redicted_field_name)页面功能

登出用户 django.contrib.auth.logout1. 出发user_logged_out singnal2. request.session.flush()3. request.user = AnonymousUser() if hasattr(request, 'user')def logout(request):    """    Removes the authenticated user's ID from the request and flushes 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()

转载于:https://my.oschina.net/alazyer/blog/907513

你可能感兴趣的文章
Scroll Depth – 衡量页面滚动的 Google 分析插件
查看>>
Windows 8.1 应用再出发 - 视图状态的更新
查看>>
自己制作交叉编译工具链
查看>>
Qt Style Sheet实践(四):行文本编辑框QLineEdit及自动补全
查看>>
[物理学与PDEs]第3章习题1 只有一个非零分量的磁场
查看>>
深入浅出NodeJS——数据通信,NET模块运行机制
查看>>
onInterceptTouchEvent和onTouchEvent调用时序
查看>>
android防止内存溢出浅析
查看>>
4.3.3版本之引擎bug
查看>>
SQL Server表分区详解
查看>>
使用FMDB最新v2.3版本教程
查看>>
SSIS从理论到实战,再到应用(3)----SSIS包的变量,约束,常用容器
查看>>
STM32启动过程--启动文件--分析
查看>>
垂死挣扎还是涅槃重生 -- Delphi XE5 公布会归来感想
查看>>
淘宝的几个架构图
查看>>
Android扩展 - 拍照篇(Camera)
查看>>
JAVA数组的定义及用法
查看>>
充分利用HTML标签元素 – 简单的xtyle前端框架
查看>>
设计模式(十一):FACADE外观模式 -- 结构型模式
查看>>
iOS xcodebuile 自动编译打包ipa
查看>>