用户认证组件
功能:用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: pass10: # 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_required3: def my_view(request):
4: pass5:
若用户没有登录,则会跳转到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 = None3: 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_required2: def set_password(request):
3: user = request.user4: state = None5: 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,最后返回给请求者。
上述截图中的中间件都是django中的,我们也可以自己定义一个中间件,我们可以自己写一个类,但是必须继承MiddlewareMixin
导入
1: from django.utils.deprecation import MiddlewareMixin
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返回,然后依次返回到请求者
流程图如下:
process_view
1: process_view(self, request, callback, callback_args, callback_kwargs)
流程图如下:
当最后一个中间的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出现错误时:
示例:
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_LIST10: if request.path in white_list :11: return None
12:13: if not request.user.is_authenticated :14: return redirect("/login/")15: