zoukankan      html  css  js  c++  java
  • Django组件之用户认证和中间件

    用户认证组件

    功能:用session记录登录验证状态

    前提:用户表 django自带的auth_user

    创建超级用户python manage.py createsuperuser

    API 如下

    一、 auth模块

      1: from django.contrib import auth

    django.contrib.auth中提供了许多方法,这里主要介绍其中的三个

    1.1 authenticate()

    提供了用户认证,即验证用户名以及密码是否正确,一般需要username password两个关键字参数</p>如果认证信息有效,会返回一个 User 对象。

    authenticate()会在User 对象上设置一个属性标识那种认证后端认证了该用户,且该信息在后面的登录过程中是需要的。

    当我们试图登陆一个从数据库中直接取出来不经过authenticate()的User对象会报错的!!

      1: user = authenticate(username='someone',password='somepassword')

    1.2 login(HttpRequest, user)

    该函数接受一个HttpRequest对象,以及一个认证了的User对象
    此函数使用django的session框架给某个已认证的用户附加上session id等信息。

      1: def my_view(request):
    
      2:     username = request.POST['username']
    
      3:     password = request.POST['password']
    
      4:     user = authenticate(username=username, password=password)
    
      5:     if user is not None:
    
      6:         login(request, user)
    
      7:     # Redirect to a success page.
    
      8:     else:
    
      9:         pass
    
     10:     # Return an 'invalid login' error message.
    
     11: 

    1.3 logout(request) 注销用户

      1: from django.contrib.auth import logout
    
      2: def logout_view(request):
    
      3:     logout(request)
    
      4:     # Redirect to a success page.

    该函数接受一个HttpRequest对象,无返回值。当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。

    二、User对象

    User 对象属性:username, password(必填项)password用哈希算法保存到数据库.

    2.1 user对象的 is_authenticated()

    如果是真正的 User 对象,返回值恒为 True 。 用于检查用户是否已经通过了认证。

    通过认证并不意味着用户拥有任何权限,甚至也不检查该用户是否处于激活状态,这只是表明用户成功的通过了认证。

    这个方法很重要, 在后台用request.user.is_authenticated()判断用户是否已经登录,如果true则可以向前台展示request.user.name

    现在有如下要求:
    1 用户登陆后才能访问某些页面,
    2 如果用户没有登录就访问该页面的话直接跳到登录页面
    3 用户在跳转的登陆界面中完成登陆后,自动访问跳转到之前访问的地址

    方法1:

      1: def my_view(request):
    
      2:   if not request.user.is_authenticated():
    
      3:     return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
    
      4: 

    方法2:

    django已经为我们设计好了一个用于此种情况的装饰器:@login_requierd

      1: from django.contrib.auth.decorators import login_required
    
      2: @login_required
    
      3: def my_view(request):
    
      4:     pass
    
      5: 

    若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' (这个值可以在settings文件中通过LOGIN_URL进行修改)。并传递 当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。

    2.2 创建用户

      1: from django.contrib.auth.models import User
    
      2: user = User.objects.create_user(username='',password='',email='')

    2.3 check_password(password)

    用户需要修改密码的时候 首先要让他输入原来的密码 ,如果给定的字符串通过了密码检查,返回 True

    2.4 修改密码

      1: user = User.objects.get(username='')
    
      2: user.set_password(password='')
    
      3: user.save()
    
      4: 

    2.5 简单示例

    注册

      1: def sign_up(request):
    
      2:     state = None
    
      3:     if request.method == 'POST':
    
      4:         password = request.POST.get('password', '')
    
      5:         repeat_password = request.POST.get('repeat_password', '')
    
      6:         email=request.POST.get('email', '')
    
      7:         username = request.POST.get('username', '')
    
      8:         if User.objects.filter(username=username):
    
      9:                 state = 'user_exist'
    
     10:         else:
    
     11:                 new_user = User.objects.create_user(username=username, password=password,email=email)
    
     12:                 new_user.save()
    
     13:                 return redirect('/book/')
    
     14:     content = {
    
     15:         'state': state,
    
     16:         'user': None,
    
     17:     }
    
     18:     return render(request, 'sign_up.html', content)
    
     19: 

    修改密码:

      1: @login_required
    
      2: def set_password(request):
    
      3:     user = request.user
    
      4:     state = None
    
      5:     if request.method == 'POST':
    
      6:         old_password = request.POST.get('old_password', '')
    
      7:         new_password = request.POST.get('new_password', '')
    
      8:         repeat_password = request.POST.get('repeat_password', '')
    
      9:         if user.check_password(old_password):
    
     10:             if not new_password:
    
     11:                 state = 'empty'
    
     12:             elif new_password != repeat_password:
    
     13:                 state = 'repeat_error'
    
     14:             else:
    
     15:                 user.set_password(new_password)
    
     16:                 user.save()
    
     17:                 return redirect("/log_in/")
    
     18:         else:
    
     19:             state = 'password_error'
    
     20:     content = {
    
     21:         'user': user,
    
     22:         'state': state,
    
     23:     }
    
     24: return render(request, 'set_password.html', content)
    
     25: 

    补充

    匿名用户的特征:

    Id永远为none,username永远为空字符串,get_username()永远返回空字符串,is_staff和is_superuser永远为false,is_active永远为False……

    总的来说不是空就是flase。

    中间件

    Middleware

    中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。

    如果你想修改请求,例如被传送到view中的HttpRequest对象。 或者你想修改view返回的HttpResponse对象,这些都可以通过中间件来实现。

    可能你还想在view执行之前做一些操作,这种情况就可以用 middleware来实现。

    Django有默认的Middleware,每一个中间件都有具体的功能。

    自定义中间件

    中间件中一共有四个方法:

    process_request
    process_view
    process_exception
    process_response

    当用户发起请求的时候会依次经过所有的的中间件,这个时候的请求时process_request,最后到达views的函数中,views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者。

    image

    上述截图中的中间件都是django中的,我们也可以自己定义一个中间件,我们可以自己写一个类,但是必须继承MiddlewareMixin

    导入

      1: from django.utils.deprecation import MiddlewareMixin

     image

      1: from django.utils.deprecation import MiddlewareMixin
    
      2: from django.shortcuts import HttpResponse
    
      3: 
    
      4: class Md1(MiddlewareMixin):
    
      5:     def process_request(self,request):
    
      6:         print("Md1请求")
    
      7:     def process_response(self,request,response):
    
      8:         print("Md1返回")
    
      9:         return response
    
     10: class Md2(MiddlewareMixin):
    
     11:     def process_request(self,request):
    
     12:         print("Md2请求")
    
     13:         #return HttpResponse("Md2中断")
    
     14:     def process_response(self,request,response):
    
     15:         print("Md2返回")
    
     16:         return response
    

    意:如果当请求到达请求2的时候直接不符合条件返回,即return HttpResponse("Md2中断"),程序将把请求直接发给中间件2返回,然后依次返回到请求者

    流程图如下:

    image

    process_view

      1: process_view(self, request, callback, callback_args, callback_kwargs)

    流程图如下:

    image

    当最后一个中间的process_request到达路由关系映射之后,返回到中间件1的process_view,然后依次往下,到达views函数,最后通过process_response依次返回到达用户。

    process_view可以用来调用视图函数:

      1: class Md1(MiddlewareMixin):
    
      2:     def process_request(self,request):
    
      3:         print("Md1请求")
    
      4:         #return HttpResponse("Md1中断")
    
      5:     def process_response(self,request,response):
    
      6:         print("Md1返回")
    
      7:         return response
    
      8:     def process_view(self, request, callback, callback_args, callback_kwargs):
    
      9:         # return HttpResponse("hello")
    
     10:         response=callback(request,*callback_args,**callback_kwargs)
    
     11:         return response
    
     12: 

    注意:process_view如果有返回值,会越过其他中间件的process_view以及视图函数,但是所有的process_response都还会执行

    process_exception

      1: process_exception(self, request, exception)

    流程图如下:

    当views出现错误时:

    image

    示例:

      1: class Md1(MiddlewareMixin):
    
      2: def process_request(self,request):
    
      3:         print("Md1请求")
    
      4:         #return HttpResponse("Md1中断")
    
      5:     def process_response(self,request,response):
    
      6:         print("Md1返回")
    
      7:         return response
    
      8:     def process_view(self, request, callback, callback_args, callback_kwargs):
    
      9:         # return HttpResponse("hello")
    
     10:         # response=callback(request,*callback_args,**callback_kwargs)
    
     11:         # return response
    
     12:         print("md1 process_view...")
    
     13:     def process_exception(self):
    
     14:         print("md1 process_exception...")
    
     15: class Md2(MiddlewareMixin):
    
     16:     def process_request(self,request):
    
     17:         print("Md2请求")
    
     18:         # return HttpResponse("Md2中断")
    
     19:     def process_response(self,request,response):
    
     20:         print("Md2返回")
    
     21:         return response
    
     22:     def process_view(self, request, callback, callback_args, callback_kwargs):
    
     23:         print("md2 process_view...")
    
     24:     def process_exception(self):
    
     25:         print("md1 process_exception...")
    
     26: 

    打印结果如下

      1: Md1请求
    
      2: Md2请求
    
      3: md1 process_view...
    
      4: md2 process_view...
    
      5: view函数...
    
      6: 
    
      7: Md2返回
    
      8: Md1返回
    

    将md2的process_exception修改如下:

      1: def process_exception(self, request, exception):
    
      2:     print("md2 process_exception...")
    
      3:     return HttpResponse("error")
    
      4: 

    结果如下:

      1: Md1请求
    
      2: Md2请求
    
      3: md1 process_view...
    
      4: md2 process_view...
    
      5: view函数...
    
      6: md2 process_exception...
    
      7: Md2返回
    
      8: Md1返回
    
      9: 

    中间件应用案例

    1、做IP访问频率限制

    某些IP访问服务器的频率过高,进行拦截,比如限制每分钟不能超过20次。

    2、URL访问过滤

    如果用户访问的是login视图(放过)
    如果访问其他视图,需要检测是不是有session认证,已经有了放行,没有返回login,这样就省得在多个视图函数上写装饰器了!

    代码示例

      1: from django.utils.deprecation import MiddlewareMixin
    
      2: from django.shortcuts import redirect
    
      3: from authDemo import settings
    
      4: 
    
      5: class AuthMiddleware(MiddlewareMixin) :
    
      6: 
    
      7:     def process_request(self, request) :
    
      8:         # 添加一个url白名单
    
      9:         white_list = settings.WHITE_LIST
    
     10:         if request.path in white_list :
    
     11:             return None
    
     12: 
    
     13:         if not request.user.is_authenticated :
    
     14:             return redirect("/login/")
    
     15: 
  • 相关阅读:
    让delphi2010能有delphi7的版面布局
    多线程的基本概念和Delphi线程对象Tthread介绍
    Delphi编写后台监控软件
    delphi 2010是动画GIF的支持方法
    delphi 资源文件详解
    delphi 基础之四 delphi 组织结构
    delphi 基础之三 编写和调用dll文件
    delphi 基础之三 文件流操作
    mysql (5.7版本)---的配置
    session--保持登录20分钟,常用与用户登录状态
  • 原文地址:https://www.cnblogs.com/haoqirui/p/10258873.html
Copyright © 2011-2022 走看看