django中间件及中间件实现的登录验证

1.定义

  一个用来处理Django的请求和响应的框架级别的钩子(函数),相对比较轻量级,并且在全局上改变django的输入与输出(使用需谨慎,否则影响性能)

  直白的说中间件就是帮助我们在视图函数执行之前和执行之后做一些额外操作

2.用处

  用户登录

  日志记录

  权限管理

  请求验证(post)

  一般对所有请求做批量处理的时候用中间件,单独对某几个函数处理直接使用装饰器

3.用法说明

  我们使用django一直就在使用中间件,打开django的setting文件,当中的MIDDLEWARE配置项

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

列表当中的每个字符串,其实是一个个类,即一个个中间件,它们正常的执行顺序都是自上而下的

中间件中,我们可以定义五个方法,分别是:

process_request(self,request)
process_view(self, request, view_func, view_args, view_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
process_response(self, request, response)

其中最常用的是process_request和process_response

以上方法的返回值可以是None或一个HttpResponse对象,如果是None,则继续按照django定义的规则向后继续执行,如果是HttpResponse对象,则直接将该对象返回给用户。

3.1 图例说明

这里还是先来看看django的生命周期图例

 先从上图了解django执行流程,每一步起了那些关键性作用,然后我们再来讨论每一个中间件

3.2 process_request与process_response  

  process_request有一个request参数,这个和视图函数中的request参数一模一样

  process_response有两个参数,一个是request,一个是response,request和前面一致,response是视图函数返回的HttpResponse对象

代码实例

  我在应用下创建了一个middlewares文件,用于存放中间件

from django.utils.deprecation import MiddlewareMixin
# 注意导入路径
class MD1(MiddlewareMixin):
def process_request(self, request):
print('我是MD1的process_request')
def process_response(self, request, response):
print('我是MD1的process_response')
return response
class MD2(MiddlewareMixin):
def process_request(self, request):
print('我是MD2的process_request')
def process_response(self, request, response):
print('我是MD2的process_response')
return response

setting.py文件配制添加的中间价位置

访问一个视图,终端输出结果:

总结:

  1.process_request方法,是在视图函数执行之前执行的,当配制多个中间件时,会按照MIDDLEWARE中的注册顺序,也就是列表的索引值,从前到后依次执行的

  返回值是None,继续往后执行,返回值是HttpResponse的对象,执行对应中间件的process_response方法

  2.对于视图函数,是在process_request执行完毕后开始执行的

  3.process_response方法,是在视图函数之后执行的,而且多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的

3.3 process_view

  process_view(self, request, view_func, view_args, view_kwargs)

该方法有四个参数:

  request是HttpRequest对象。

  view_func是Django即将使用的视图函数。 (它是实际的函数对象,而不是函数的名称作为字符串。)

  view_args是将传递给视图的位置参数的列表.

  view_kwargs是将传递给视图的关键字参数的字典。 view_args和view_kwargs都不包含第一个视图参数(request)。

代码实例

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render, redirect, HttpResponse
class MD1(MiddlewareMixin):
def process_request(self, request):
print('我是MD1的process_request')
def process_response(self, request, response):
print('我是MD1的process_response')
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print('我是MD1的process_view')
print(view_func, view_func.__name__)

class MD2(MiddlewareMixin): def process_request(self, request): print('我是MD2的process_request') # return HttpResponse('MD2process_request') def process_response(self, request, response): print('我是MD2的process_response') return response def process_view(self, request, view_func, view_args, view_kwargs): print('我是MD2的process_view') print(view_func, view_func.__name__)

效果

总结:

  1.process_view是在视图执行前执行的,process_request之后,执行顺序按照MIDDLEWARE中的注册顺序从前到后顺序执行的

3.4 process_exception

  process_exception(self, request, exception)

该方法两个参数:

  一个HttpRequest对象

  一个exception是视图函数异常产生的Exception对象。

 该方法只有在视图函数中出现异常才会执行,如果视图函数中无异常,process_exception方法不执行。

代码实例

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render, redirect, HttpResponse
class MD1(MiddlewareMixin):
def process_request(self, request):
print('我是MD1的process_request')
def process_response(self, request, response):
print('我是MD1的process_response')
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print('我是MD1的process_view')
print(view_func, view_func.__name__)
def process_exception(self, request, exception):
print(exception, '这是MD1的process_exception')
# return HttpResponse(str(exception))
class MD2(MiddlewareMixin):
def process_request(self, request):
print('我是MD2的process_request')
# return HttpResponse('MD2process_request')
def process_response(self, request, response):
print('我是MD2的process_response')
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print('我是MD2的process_view')
print(view_func, view_func.__name__)
# return HttpResponse('这是MD2的process_view')
def process_exception(self, request, exception):
print(exception, '这是MD2的process_exception')
return HttpResponse(str(exception))  # 返回一个响应对象

在视图函数index中抛出一个异常

def index(request):
print('app01中的index视图')
raise ValueError("6666")
return HttpResponse('这是index页面')

此时结果:

# 可以从结果看出来,exception接收的就是异常信息,我们的MD1并没有return HttpResponse(str(exception)) ,但是它却也抛出了异常信息

总结:

  1.只要视图函数报错了才执行

  2.在视图函数之后,process_response之前

3.5 process_template_response(不常用)

  process_template_response是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法

4.中间件执行流程

  请求到达中间件之后,如果MIDDLEWARE中注册了6个中间件,执行过程中,第3个中间件返回了一个HttpResponse对象,那么第4,5,6中间件的process_request和process_response方法都不执行,顺序执行3,2,1中间件的process_response方法

process_request方法都执行完后,匹配路由找到要执行的视图函数,先不执行视图函数,先执行中间件中的process_view方法,process_view方法返回None,继续按顺序执行,所有process_view方法执行完后执行视图函数。假如中间件3 的process_view方法返回了HttpResponse对象,则4,5,6的process_view以及视图函数都不执行,直接从最后一个中间件,也就是中间件6的process_response方法开始倒序执行。

中间件的执行顺序:

5.中间件实现登录验证

  以下代码还具有阻隔功能,即必须先登录才能访问主页,直接从url访问index会拒绝请求

代码实例:

  urls.py

urlpatterns = [
path('admin/', admin.site.urls),
path('login/', views.login),
path('logout/', views.logout),
path('index/', views.index),
path('home/', views.home),
]
View Code

views.py

from django.shortcuts import render, HttpResponse, redirect
from django.contrib import auth
import json
# Create your views here.
def login(request):
if request.method == "POST":
user = request.POST.get("user")
pwd = request.POST.get("pwd")
ret = {"status": 0, 'url': ''}
if user == "xiao" and pwd == "123":
# 设置session
request.session["user"] = user
ret['status'] = 1
# 跳转到index页面
ret['url'] = '/index/'
return HttpResponse(json.dumps(ret))
return render(request, "login.html")
def logout(request):  # 注销
    auth.logout(request)
return redirect("/login/")
def index(request):
return HttpResponse('this is index <a href="/logout/">注销</a>')
def home(request):
return HttpResponse('this is home')
View Code

应用app01下的middlewares.py

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render, redirect, HttpResponse
class AuthMD(MiddlewareMixin):  # 验证登录
white_list = ['/login/', ]  # 白名单
black_list = ['/black/', ]  # 黑名单
ret = {"status": 0, 'url': '', 'msg': ''}  # 默认状态
def process_request(self, request):  # 请求之前
request_url = request.path_info  # 获取请求路径
# get_full_path()表示带参数的路径
print(request.path_info, request.get_full_path())
# 黑名单的网址限制访问
if request_url in self.black_list:
self.ret['msg'] = "这是非法请求"
self.ret['url'] = "/login/"
# 白名单的网址或者登陆用户不做限制
# 判断是否在白名单内或者已经有了session(表示已经登录了)
elif request_url in self.white_list or request.session.get("user"):
return None
else:
self.ret['msg'] = "请登录后,再访问!"
self.ret['url'] = "/login/"
# 错误页面提示
return render(request, "jump.html", self.ret)
View Code

settings.py的MIDDLEWARE配置项

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'app01.middlewares.AuthMD',  # 自定义中间件AuthMD
]
View Code

jump.html,用来做中间件不通过时,js跳转

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<link rel="stylesheet" href="http://mishengqiang.com/sweetalert/css/sweetalert.css">
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="http://mishengqiang.com/sweetalert/js/sweetalert-dev.js"></script>
<div>
{#获取错误信息#}
<input type="hidden" id="msg" value="{{ msg }}">
<input type="hidden" id="url" value="{{ url }}">
</div>
<script>
$(function () {
var msg = $("#msg").val();
var url = $("#url").val();
console.log(msg);
console.log(url);
if (msg.length > 0) {  //判断是否有错误信息
swal({
title: msg,
text: "2秒后自动关闭。",
type: 'error',
timer: 2000,
showConfirmButton: false
}, function () {
window.location.href = url;  //跳转指定url
});
}
})
</script>
</body>
</html>
View Code

# 这里的定制化错误信息效果相当不错,可以拿来借鉴

login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>登录</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="/static/css/signin.css">
</head>
<body>
<div class="container">
<form class="form-signin">
{% csrf_token %}
<h2 class="form-signin-heading">请登录</h2>
<label for="inputUser" class="sr-only">用户名</label>
<input type="text" id="inputUser" class="form-control" placeholder="用户名" required="" autofocus="" name="user">
<label for="inputPassword" class="sr-only">密码</label>
<input type="password" id="inputPassword" class="form-control" placeholder="密码" required="" name="pwd">
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me"> 记住我
</label>
</div>
<input class="btn btn-lg btn-primary btn-block" id="login" value="登陆">
</form>
</div> <!-- /container -->
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
{#必须先引入jquery,再引入cookie#}
<script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
{#sweetalert插件#}
<link rel="stylesheet" href="http://mishengqiang.com/sweetalert/css/sweetalert.css">
<script src="http://mishengqiang.com/sweetalert/js/sweetalert-dev.js"></script>
<script>
//ajax在发送之前,做的header头。csrfSafeMethod是一个方法名,用来调用的
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
//这些HTTP方法不需要CSRF保护
// 匹配method的请求模式,js正则匹配用test
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$('#login').click(function () {
$.ajax({
url: '/login/',
type: 'post',
//增加X-CSRFToken的请求头
headers:{ "X-CSRFToken":$.cookie('csrftoken') },
data: {
user: $('[name="user"]').val(),
pwd: $('[name="pwd"]').val()
},
success: function (data) {
data = JSON.parse(data);
if (data.status) {
swal({
title: '登录成功',
type: 'success',  //展示成功的图片
timer: 500,  //延时500毫秒
showConfirmButton: false  //关闭确认框
}, function () {
window.location.href = data.url;  //跳转后台首页
});
}
else {
sweetAlert("登录失败!", data.msg, "error");
}
}
})
})
</script>
</body>
</html>
View Code

 


更多专业前端知识,请上 【猿2048】www.mk2048.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/363048.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二进制和十进制的相互转换

十进制转二进制&#xff1a; 方法一&#xff1a;y…… 25 * x 24 * x 23 * x 22 * x 21 * x 20 * x&#xff0c;其中y是十进制数字&#xff0c;x是0或1。 方法二&#xff1a; 二进制转十进制&#xff1a; 10100125 * 1 24 * 0 23 * 1 22 * 0 21 * 0 20 * 141 更多专业前端知…

Hadoop开发工具简介

几天前&#xff0c; Apache Hadoop开发工具 &#xff08;又名HDT &#xff09;发布了。 这些项目旨在将插件引入eclipse中&#xff0c;以简化Hadoop平台上的开发。 该博客旨在概述HDT的一些重要功能。 单端点 该项目可以充当HDFS&#xff0c;Zookeeper和MR群集的单个端点。 您…

使用Spring MVC时的常见错误

当我大约10年前开始我的职业生涯时&#xff0c;Struts MVC就是市场上的常态。 但是&#xff0c;多年来&#xff0c;我观察到Spring MVC逐渐流行起来。 鉴于Spring MVC与Spring容器的无缝集成以及它提供的灵活性和可扩展性&#xff0c;这对我来说并不奇怪。 从到目前为止的Spri…

C++ operator操作符重载(++,--,-,+,())

C中,--操作符重载需要说明是(--)在操作数前面,还是在操作数后面,区别如下: 代码经过测试无误(起码我这里没问题^_^)Code1#include <iostream> 2#include <cstdlib> 3using namespace std; 4template<typename T> class A 5{ 6public: 7 A(): m_(0){ 8 …

javax.el.PropertyNotFoundException: Property [Xxxx] not found on type Xxx.xxx.xxxx.Xxxx]的解决办法...

当我将后台数据传递给jsp&#xff0c;用${requestScope.user.Id}取值时报错&#xff0c; 最后发现entity实体类的属性不能首字母大写然后再小写&#xff0c;例如 int Age&#xff1b;这个就不行&#xff0c;必须写成int age; 最后问题解决了 转载于:https://www.cnblogs.com/Th…

初识C语言(五)

自定义函数 C语言提供了大量的库函数&#xff08;右侧资料下载中有&#xff09;&#xff0c;比如stdio.h提供输出函数&#xff0c;但是还是满足不了我们开发中的一些逻辑&#xff0c;所以这个时候需要自己定义函数&#xff0c;自定义函数的一般形式&#xff1a; 注意&#xff1…

nodeJS实现简单网页爬虫功能

前面的话 本文将使用nodeJS实现一个简单的网页爬虫功能 网页源码 使用http.get()方法获取网页源码&#xff0c;以hao123网站的头条页面为例 http://tuijian.hao123.com/hotrank var http require(http);http.get(http://tuijian.hao123.com/hotrank,function(res){var data ;…

JavaFX技巧6:使用透明颜色

为用户界面元素选择正确的颜色始终是一个很大的挑战&#xff0c;但是当您开发可重用的框架控件时&#xff0c;开发人员就无法控制使用它们的应用程序的外观和感觉&#xff0c;这甚至更具挑战性。 尽管您可能总是将元素添加到默认的灰色背景之上&#xff0c;但是嵌入控件的开发人…

38.QT-QAxObject快速写入EXCEL示例

参考链接: https://blog.csdn.net/czyt1988/article/details/52121360 http://blog.sina.com.cn/s/blog_a6fb6cc90101gv2p.html 1. QAxObject介绍 在QT中,有个自带的QAxObject类,可以直接操作EXCEL 除此之外,当我们操作某个文件夹下的EXCEL的时候,都会在该文件夹下出现一个隐藏…

EA常见画图(类图、包图、构件图、状态图、顺序图、活动图)

EA常见活动图&#xff0c;状态图画法 类图:111&#xff08;1&#xff09;给关系添加注释&#xff08;2&#xff09;设置关系线样式 包图&#xff1a;&#xff08;1&#xff09;创建包图&#xff08;2&#xff09;在包中添加子包&#xff1a;&#xff08;3&#xff09;在包中添加…

我最喜欢的IntelliJ IDEA功能

我已经是IntelliJ IDEA的长期用户&#xff08;和客户&#xff09;。 我想我是在2005年或2006年&#xff08;版本5.0&#xff09;左右开始使用它的。 那时我是Eclipse用户。 我的一些同事向我推荐了它&#xff0c;起初我没有被说服&#xff0c;但是在尝试之后我印象深刻。 现在…

selenium 常见问题

启动selenium时报错如下异常&#xff1a; selenium.common.exceptions.WebDriverException: Message: geckodriver executable needs to be in PATH. 解决方式&#xff1a;需要下载geckodriver&#xff0c;并放在path的环境变量下&#xff0c;下载地址&#xff1a;https://gith…

通过示例了解挥发

我们已经花了几个月的时间来稳定Plumbr中的锁定检测功能 。 在此期间&#xff0c;我们遇到了许多棘手的并发问题。 许多问题是独特的&#xff0c;但是一种特殊类型的问题一直反复出现。 您可能已经猜到了–滥用volatile关键字。 我们已经发现并解决了许多问题&#xff0c;其中…

HDU 1212 Big Number

题意&#xff1a;给一数字字符串s ( ns.size()<1000 ) 和数字m (<1e5) 求s%m 模拟除法&#xff0c; k初值0&#xff0c;按s[0]...累乘相加&#xff0c;把字符串还原成数字&#xff0c;比m大时-m&#xff0c;继续按位还原到s[n-1] 此时剩下的k再%m即为所求 #include<…

BOM之navigator对象和用户代理检测

前面的话 navigator对象现在已经成为识别客户端浏览器的事实标准&#xff0c;navigator对象是所有支持javascript的浏览器所共有的。本文将详细介绍navigator对象和用户代理检测 属性 与其他BOM对象的情况一样&#xff0c;每个浏览器中的navigator对象也都有一套自己的属性。下…

智能自动PPR更改事件策略

ADF开发人员普遍认为&#xff0c;将迭代器绑定更改事件策略设置为ppr在性能方面不是一件好事&#xff0c;因为此策略会强制框架刷新每个请求上绑定到此迭代器的所有属性绑定。 这不是真的&#xff01; 框架仅刷新在请求期间已更改的属性和依赖于已更改属性的属性。 让我们考虑…

装饰器设计模式的应用

嗨&#xff0c;您好&#xff01; 今天&#xff0c;我将展示装饰设计模式的实际应用。 装饰器设计模式是一种广泛使用的设计模式&#xff0c;同时在运行期间处理图形&#xff0c;树木和动态更改。 如果您正在寻找或尝试进行递归&#xff0c;这也是一个不错的选择。 我喜欢它。…

构造函数 基本使用

相关知识点&#xff1a; 构造函数、原型对象、实例对象 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta h…

Vista,Windows7中给IIS7添加PHP支持

截止到发文时&#xff08;2009年9月25日&#xff09;&#xff0c;PHP是最新版本为5.3.0&#xff0c;但是5.3.0在IIS中的运行方式是FastCGI&#xff0c;要在Vista的IIS7上实现这一点我始终没弄成。最后我还是用的老方法&#xff0c;ISAPI&#xff0c;选用了一个5.3以前的版本&am…

python画手绘图

第一步&#xff1a;插入代码 #e17.1HandDrawPic.py from PIL import Image import numpy as np vec_el np.pi/2.2 # 光源的俯视角度&#xff0c;弧度值 vec_az np.pi/4. # 光源的方位角度&#xff0c;弧度值 depth 10. # (0-100) im Image.open(C:\\Users\\Thinkpad\\Deskt…