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: 

猜你喜欢

转载自www.cnblogs.com/haoqirui/p/10258873.html
今日推荐