django 中间件,auth模块

django 中间件,auth模块

django请求生命周期流程图

django中间件

前戏

在前面的博客中已经学会了给视图函数加装饰器来判断是用户是否登录,把没有登录的用户请求跳转到登录页面。我们通过给几个特定视图函数加装饰器实现了这个需求。但是以后添加的视图函数可能也需要加上装饰器,这样是不是稍微有点繁琐。

中间件

他就像相当于django的门户,通俗一点就是阻止你进门的保安,需要验证。

只要是全局相关的功能你都应该考虑使用django中间件来帮你完成

全局用户身份校验
全局用户访问频率校验
用户访问黑名单
用户访问白名单

中间件介绍

什么是中间件:

中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。
中间件是帮助我们在视图函数执行之前和执行之后都可以做一些额外的操作,它本质上就是一个自定义类,类中定义了几个方法,Django框架会在请求的特定的时间去执行这些方法。

注意:

但是由于其影响的是全局,所以需要谨慎使用,使用不当会影响性能。

中间件代码

只要以后用django开发业务 设计到全局相关的功能 你就考虑用中间件

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',
]

django支持用户自定义中间件

中间件可以定义六个方法,分别是:(主要的是process_request和process_response)

class SessionMiddleware(MiddlewareMixin):
    def process_request(self, request):

    def process_response(self, request, response):

class CsrfViewMiddleware(MiddlewareMixin):
    def process_request(self, request):

    def process_view(self, request, callback, callback_args, callback_kwargs):

    def process_response(self, request, response):


class AuthenticationMiddleware(MiddlewareMixin):
    def process_request(self, request):
以上方法的返回值可以是None或一个HttpResponse对象,如果是None,则继续按照django定义的规则向后继续执行,如果是HttpResponse对象,则直接将该对象返回给用户

自定义一个中间件示例

django运行用户自定义中间件并且暴露给用户五个可以自定义的方法

process_request

请求来的时候会按照配置文件中注册的中间从上往下的顺序依次执行每一个中间件里的process_request方法,如果没有直接跳过执行下一个同级别返回,并不会全部执行process_resquest
process_request有一个参数,就是request,这个request和视图函数中的request是一样的
由于request对象是一样的,所以我们可以对request对象进行一系列的操作,包括request.变量名=变量值,这样的操作,我们可以在后续的视图函数中通过相同的方式即可获取到我们在中间件中设置的值。
它的返回值可以是None也可以是HttpResponse对象。返回值是None的话,按正常流程继续走,交给下一个中间件处理,如果是HttpResponse对象,Django将不执行视图函数,而将相应对象返回给浏览器。

代码:

process_response(*****)

相应走的时候会按照配置文件中注册的中间件从下往上的顺序依次执行每一个中间件里面的process_response方法,该方法必须要有两个形参,并且需要将形参respondse返回
如果你内部自己返回了HttpResponse对象 会将返回给用户浏览器的内容替换成你自己的

1579008159401

1579008187731

同级别下

process_view

路人匹配成功执行视图函数之前触发

process_template_reponse

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

该方法有四个参数

request是HttpRequest对象。

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

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

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

Django会在调用视图函数之前调用process_view方法。
它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。 如果它返回一个HttpResponse对象,那么将不会执行Django的视图函数,而是直接在中间件中掉头,倒叙执行一个个process_response方法,最后返回给浏览器
视图函数返回的对象中必须要有render属性对应的render方法
视图函数返回的对象中必须要有render属性对应的render方法
def index(request):
    print('我是视图函数index')
    def render():
        return HttpResponse("你好啊 我是index里面的render函数")
    obj = HttpResponse("index")
    obj.render = render
    return obj

process_exception

当视图函数报错的时候自动触发
该方法两个参数:
一个HttpRequest对象

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


这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常。如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。

跨站请求伪造csrf

钓鱼网站

本质搭建一个跟正常网站一模一样的页面
用户在该页面上完成转账功能

转账的请求确实是朝着正常网站的服务端提交
唯一不同的在于收款账户人不同

给用户书写form表单 对方账户的input没有name属性
你自己悄悄提前写好了一个具有默认的并且是隐藏的具有name属性的input
模拟钓鱼网站





要做一个网站跟他一样



效果:给用户转的钱到钓鱼网站的用户账上去了

解决钓鱼网站问题:

form表单如何通过csrf校验的三种方式

form表单如何通过csrf校验
你只需要在你的form表单内写一个
{% csrf_token %}

ajax如何通过csrf校验 三种方式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<h2>我是正儿八经的网站</h2>
<form action="" method="post">
{#    {% csrf_token %}#}
    <p>username:<input type="text" name="username"></p>
    <p>target_user:<input type="text" name="target_user"></p>
    <p>money:<input type="text" name="money"></p>
    <input type="submit">
</form>
<button id="d1">发送ajax请求</button>


{#{% load static %}#}
{#<script src="{% static 'myset.js' %}"></script>#}
{#<script>#}
{#    $('#d1').click(function () {#}
{#        $.ajax({#}
{#            url:'',#}
{#            type:'post',#}
            {#data:{'username':'jason'},#}
{#            // 第一种方式 自己手动获取#}
             {#data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},#}
{#            // 第二种方式 利用模板语法#}
            {#data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},#}
{#            // 第三种     通用方式 引入外部js文件#}
{#            data:{'username':'jason'},#}
{#            success:function (data) {#}
{#                alert(data)#}
{#            }#}
{#        })#}
{#    })#}
{#</script>#}
</body>
</html>
// 第一种方式 自己手动获取
{#data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},#}
    // 第二种方式 利用模板语法
    {#data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},#}
        // 第三种     通用方式 引入外部js文件  官网提供的方式
        {% load static %}
        <script src="{% static 'myset.js' %}"></script>
        data:{'username':'jason'}
        

csrf相关装饰器

当我们网站整体都校验csrf的时候 我想让某几个视图函数不校验

当我们网站整体都不校验csrf的时候 我想让某几个视图函数校验
给CBV加装饰器 推荐你使用模块method_decorator
我们自己写的装饰器和csrf_protect用法一致
唯独csrf_exempt是一个特例 只能给dispatch方法装

导入:

from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.views import View9
from django.utils.decorators import method_decorator
# @method_decorator(csrf_protect,name='post')  # 第二种指名道姓的给类中某个方法装
# @method_decorator(csrf_exempt,name='post')  # csrf_exempt 第二种方式不行
@method_decorator(csrf_exempt,name='dispatch')  # 可以!!!
class MyHome(View):  # APIView
    # @method_decorator(csrf_protect)  # 第三种 类中所有的方法都装
    # @method_decorator(csrf_exempt)  # csrf_exempt 第三种方式可以
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request,*args,**kwargs)

    def get(self,request):
        return HttpResponse('get')
    # @method_decorator(csrf_protect)  # 第一种方式
    # @method_decorator(csrf_exempt)  # csrf_exempt 第一种方式不行
    def post(self,request):
        return HttpResponse('post')

auth模块

创建表

django用户相关的自带的功能模块   auth_user表

如何创建超级用户

createsuperuser

模块导入

from django.contrib import auth
from django.contrib.auth.models import User

auth方法大全

1.创建用户

User.objects.create()  # 密码是明文
User.objects.createuser()  # 基本都用它 
User.objects.createsuperuser()  # 邮箱要给数据

2.校验用户名和密码是否正确

auth.authenticate(username=username,password=password)  # 用户名和密码两个一个都不能少
# 该方法当用户名和密码正确的时候返回的用户对象 不正确返回None

3.保存用户登录状态

auth.login(request,user_obj)  # 这一句执行之后 request.user获取当前登录的用户对象

4.如何判断当前用户是否登录 以及如何获取当前登录用户对象

request.user.is_authenticated()  # 判断是否登录
request.user  # 登录用户对象

5.校验用户是否登录

局部配置 全局配置
from django.contrib.auth.decorators import login_required
# 局部配置
@login_required(login_url='/login/')
def xxx(request):
    return HttpResponse('xxx页面')

# 全局配置
配置文件中写以下代码
LOGIN_URL = '/login/'
@login_required
def xxx(request):
    return HttpResponse('xxx页面')

# 如果两个都设置了 那么优先执行局部配置

6.修改密码

request.user.check_password(old_password)  # 校验原密码是否正确

request.user.set_password(new_password)
request.user.save()                        # 一定要保存 

7.注销功能

auth.logout(request)

如何扩展auth_user表

1 利用一对一表关系()

2 利用类的继承

# 2 利用类的继承
# 1 类的继承
from django.contrib.auth.models import User,AbstractUser
# Create your models here.
class Userinfo(AbstractUser):
    phone = models.BigIntegerField()
    avatar = models.FileField()
    # 扩展的字段 尽量不要与原先表中的字段冲突

    # 2 配置文件
    AUTH_USER_MODEL = '应用名.表名'

总结:

django就会将userinfo表来替换auth_user表
并且之前auth模块所有的功能不变 参照的也是userinfo表

猜你喜欢

转载自www.cnblogs.com/WQ577098649/p/12194357.html