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,一经查实,立即删除!

相关文章

默认方法:Java 8的无名英雄

几周前&#xff0c;我写了一个博客&#xff0c;说开发人员学习新语言是因为它们很酷。 我仍然坚持这个主张&#xff0c;因为关于Java 8的事情真的很酷。 毫无疑问&#xff0c;该节目的明星是添加了Lambdas以及将函数提升为一等变量&#xff0c;而我目前最喜欢的是默认方法。 这…

用phpstudy配置网站遇到的一些问题

第一次是配置在我本机&#xff0c;总是连不上数据库&#xff0c;后来查看到mysql.ini配置文件里面端口号有一个不是3306&#xff0c;更改之后就好了。 第二次是配置在笔记本电脑上&#xff0c;安装的时候比较顺利&#xff0c;也就遇到80端口被占用还有缺少VC运行库的问题&#…

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

十进制转二进制&#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 更多专业前端知…

Teradata Expression 12 在Windows 2003上Connection Reset 问题的解决方法

Teradata Expression 12 安装在Windows 2003上&#xff08; 企业版 sp2&#xff09;&#xff0c;完全按照安装手册指导安装。安装过程一切顺利。完成后重启系统。通过Teradata Service Control启动一切正常。状态显示Teradata Running&#xff0c;打开session info ,可以看到一…

Hadoop开发工具简介

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

分布式理论之一:Paxos算法的通俗理解

https://www.cnblogs.com/esingchan/p/3917718.html转载于:https://www.cnblogs.com/JBLi/p/10732044.html

UML 面向对象分析与设计

面向对象方法以其超越传统方法的技术先进性越来越得到更多的重视&#xff0c;但技术的先进性不能完全代表一种新生事物的最后成功&#xff0c;还要看它是否能得到有效的推广。统一建模语言&#xff08;UML&#xff09;的产生为这种推广规定了一致的表示&#xff0c;诸多开发过程…

MVC 之var与dynamic

如果你用MVC写过程序&#xff0c;那么你应该知道ViewBag这个用于前后台的数据传递工具&#xff0c;那么你是否对ViewBag的用法感到过疑惑呢&#xff1f; ViewBag.Mode1lnew object();ViewBag.Model2new object();ViewBag.Model3new object();...... 我们知道&#xff0c;在使用…

使用Spring MVC时的常见错误

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

CopyOnWriteArrayList

CopyOnWriteArrayList&#xff0c;add&#xff0c;引用赋值是原子操作吗&#xff1f; 引用类型的读写均是原子操作&#xff0c;https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.7&#xff0c;https://www.v2ex.com/t/280788 转载于:https://www.cnblogs…

Statement与PreparedStatement区别

1.性能区别 Statement statement conn.createStatement(); PreparedStatement preStatement conn.prepareStatement(sql); 执行的时候: ResultSet rSet statement.executeQuery(sql); ResultSet pSet preStatement.executeQuery(); 由上可以看出&#xff0c;PreparedState…

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

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

CSS3-2

倒圆角 <!DOCTYPE html><html lang"en"><head> <meta charset"UTF-8"> <title>Document</title></head><body> <h1>圆角边框 —— border-radius IE9</h1> <!-- border-radius 是复合属性…

JavaFX技巧9:请勿混用Swing / JavaFX

JavaFX团队非常努力地说服我们&#xff0c;因为可以将Swing内容嵌入JavaFX UI中&#xff0c;因此可以很容易地从Swing迁移到JavaFX。 我必须承认&#xff0c;我从来没有亲自尝试过&#xff0c;但是根据我从客户那里得到的反馈&#xff0c;我只能建议不要将Swing和JavaFX混合使用…

[ZJJOI2013]K大数查询 整体二分

[ZJJOI2013]K大数查询 链接 luogu 思路 整体二分。 代码 #include <bits/stdc.h> #define ll long long using namespace std; const ll _5e57; ll read() {ll x0,f1;char sgetchar();for(;s>9||s<0;sgetchar()) if(s-) f-1;for(;s>0&&s<9;sgetchar(…

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…

react学习目录

前面的话 React是如今热门的两大前端框架之一&#xff0c;它设计思路独特&#xff0c;性能卓越&#xff0c;逻辑简单&#xff0c;受到了大量开发者的喜爱。Vue的基本思路是基于HTML模板的扩展&#xff0c;而React的基本思路是基于JS语言的扩展。由于Vue的写法更接近于传统&…

JavaFX技巧13:学习Modena CSS文件

到目前为止&#xff0c;这是最简单&#xff0c;最短的提示。 如果要执行以下任何操作&#xff1a; 了解如何使用CSS 使您的自定义控件看起来像标准控件 重用标准控件使用的SVG路径图形&#xff08;例如&#xff0c;滚动条箭头&#xff09; 弄清楚如何浏览标准控件的结构 确…

委托之异步

在 使用BackgroundWorker组件 一文中&#xff0c;阐述了在Winform编程中&#xff0c;使用BackgroundWorker组件实现异步调用&#xff0c;本文主要讲述利用委托实现异步。 以下描述摘抄于MSDN: 异步委托提供以异步方式调用同步方法的能力。 当同步调用委托时&#xff0c;Invoke(…

[NOI2010]超级钢琴 主席树

[NOI2010]超级钢琴 链接 luogu 思路 和12省联考的异或粽子一样。 堆维护n个左端点&#xff0c;每次取出来再放回去次 代码 #include <bits/stdc.h> #define ll long long using namespace std; const int _5e57,INF0x3f3f3f3f; int read() {int x0,f1;char sgetchar();fo…