用户认证组件
功能:用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,最后返回给请求者。
上述截图中的中间件都是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_LIST
10: if request.path in white_list :
11: return None
12:
13: if not request.user.is_authenticated :
14: return redirect("/login/")
15: