中间件&csrf&auth认证

django 中间件

web服务网关接口:
WSGI 是一种协议。
wsgiref 与uwsgi都是基于WSGI协议的一种web服务网关接口。

django中间件:
默认有七个中间键:

请求来的时候依次执行process_request方法
请求走的时候依次执行process——response方法

django中间件:全局访问频率限制,身份校验,黑名单、白名单

django中间键会依次从上往下走settings下的MIDDLEWARE中间件

中间件&csrf&auth认证_第1张图片

如何自定义中间键:
在项目下新建一个文件夹(任意名)以下称为MyMiddleware,在MyMiddleware下新建一个mymiddleware.py文件
mymiddleware.py文件下引入模块,并且定这样一个类:

from django.utils.deprecation import MiddlewareMixin
from  django.shortcuts import HttpResponse
class MyMiddleWare(MiddlewareMixin):
    def process_request(self,request):
        print('im the  first request')
        
    def process_response(self,request,response):
        print('im the  first response')
        return response

在settings的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',
    'Mymiddleware.mymiddleware.MyMiddleWare'
]

这样就完成了一个基本的中间件定义。

注:自定义中间件中带response形参的必须return repsonse,返回的是一个页面结果,如果不这样做的话,结果会丢失。

在process_request中直接return 数据(HttpResponse或Render,会直接走右边的process_response)

中间件&csrf&auth认证_第2张图片
在process_view中return会走process_response的最下面一层,依次走完process_response
中间件&csrf&auth认证_第3张图片
其他中间件:
process view 在路由匹配成功,视图启动之前。urls.py – views.py 之间执行。
process_exception 捕获views.py中视图函数的报错。
process_template 在视图函数views.py 渲染页面的时候会执行。

注:自定义中间件中带response形参的必须return repsonse,返回的是一个页面结果,如果不这样做的话,结果会丢失。

csrf(跨站请求伪造)

先写一个简单的post请求,复现报错信息

钓鱼网站:银行转账的路径,你是否也可以拿到,然后你做一个跟银行一模一样的页面,也超银行的借口提交数据,当用户在钓鱼网站输入对方账户名和转账金额之后,点击发送。其实内部是将对方账户换成了钓鱼网站的造假人员的账户。造成你转账转错账户的情况

开两个django项目,模拟转账的现象

如何区分钓鱼网站和正经网站?在正经网站返回页面的时候,在form表单中偷偷塞一个特殊的字符串,后端记下改页面对应的字符串的值,等用户发post请求来的时候,我先去校验特殊的字符串是否匹配

如何去写这个特殊的字符串呢?模版语法有一个固定的写法{% csrf_token %},必须写在form表单内

浏览器查看改标签的值,并且每次都在刷新。再来演示刚刚转账的示例

csrf 的开启与禁用

局部禁用csrf

#引入csrf装饰器
from django.views.decorators.csrf import csrf_exempt,csrf_protect

@csrf_exempt
def home(reqeust):
	return HttpResponse('ok')](https://img-blog.csdnimg.cn/20190423155317645.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM2MDE5NDkw,size_16,color_FFFFFF,t_70)

局部启用csrf校验

网站没有启动csrf校验的情况下局部启用
views.py

@csrf_protect
def login(request):
	return Httpresponse('login')

html下
1.form表单中:下面插入以下代码

{%csrf_token%}

2.ajax如何通过csrf校验
ajax提交:除了在form表单中插入{%csrf_token%}
还需在script脚本中插入以下ajax代码(注:script脚本写在最下方)
本段代码的重点是,我们在提交data数据的时候需要把csrfmiddlewaretoken作为键,用jquery选择器找到csrfmiddlewaretoken的值,作为data的一部分提交上去,这样就不会导致csrf引起的403forbidden.
中间件&csrf&auth认证_第4张图片

中间件&csrf&auth认证_第5张图片

CBV(class base views)基于类的视图函数通过csrf校验

urls.py 路由层(Myview是个类)

url('^index/',views.Myview.as_view())

views.py 视图层
两种方式,见图:
中间件&csrf&auth认证_第6张图片

auth认证:

先执行以下语句

python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser  #创建超级用户

views.py

from django.shortcuts import render,HttpResponse,redirect



from django.contrib import auth   #用于存储登陆信息及对表的查询
from django.contrib.auth.models import  User # 创建对应表的时候会用到


def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        user = auth.authenticate(request,username=username,password=password) #查表,查到符合的返回user对象
        if user : #如果user对象的返回结果有值,即从前端获取到了对象
            auth.login(request,user) #相当于操作seesion记录,执行过后其他视图函数可以直接通过request.user获取当前用户对象。
            return HttpResponse('登陆成功')
    return render(request,'login.html')

def index(request):
    print(request.user.is_authenticated)  #判断是否处于登陆状态
    print(request.user.username)          #获取登录名
    print(request.user.password)          #获取登陆密码
    return HttpResponse('index')


def logout(request):
    auth.logout(request)  #相当于request.session.flush()清空session中的键值
    return HttpResponse('注销成功')  #注销当前用户

#给函数加上一个“验证是否已经登陆”的装饰器【中间件中亦可处理】
from django.contrib.auth.decorators import login_required

#局部装饰器会自动校验你是否登陆,检验你的session信息,不需要其他
@login_required(login_url='/login/')  #设定未登录状态时候的跳转页面
def home(request):
    return HttpResponse('home')
#>>> http://127.0.0.1:8000/accounts/login/?next=/home/       #给出了一个错误跳转

#全局装饰器验证是否登陆进行跳转,在settings配置文件中进行配置,就不需要在局部配置了
#LOGIN_URL = '/login/'

def register(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        User.objects.create_user(username=username,password=password)
        #User.objects.create_superuser(username=username,password=password) #创建超级用户,必须包含email字段,这里没有添加。
        #User.objects.create(username=username,password=password) 密码不是密文的,在auth中不要使用此种方式创建用户
    return render(request,'register.html')#创建表对象


#校验密码 修改密码
def set_password(request):
#jonathan666是原密码,jonathan777是新密码,这里偷懒没从前端获取数据
    res = request.user.check_password('jonathan666')
    if res:
        request.user.set_password('jonathan888')
        request.user.save()
        return HttpResponse('ok')

图1:session_key对应网页中的session_id。session_data对应的就是user的数据
在这里插入图片描述

在默认的auth表中新建其他字段

from django.db import models

# Create your models here.

	# 扩展auth_user表
	# 方式一(不推荐):
	# 一对一关联
	# class UserDetail(models.Model):
	#   phone = models.CharField(max_length=11)
	#   user = models.OneToOneField(to=User)
	# 方式二(推荐):
	# 在setttings.py中设置
	# AUTH_USER_MODEL = "app名.models对应的表名"
	# 目的是告诉django不再使用默认的auth_user表,而使用我自己创建的Userinfo表
	# AUTH_USER_MODEL = "app01.Userinfo"
from django.contrib.auth.models import AbstractUser
class Userinfo(AbstractUser):  # 继承 AbstractUser表中的所有字段
	avator = models.CharField(max_length=32)
# 注释:对数据的增删改查仍旧是用app01.model下的模型表,创建表的的方式create和create_user、create_superuser都可以使用,不同之处在于,create_user对密码字段进行了加密,create_superuser对密码字段进行了加密,并且创建超级用户那一栏为1。
	原来数据库的其他操作:
	-authentication
	-login
	-logout
	-set_password
	一样用,不一样的地方在于之前用到USER 表模型的地方都改成USERINFO

参考:https://www.cnblogs.com/liuqingzheng/articles/9628105.html

https://www.cnblogs.com/Dominic-Ji/p/9229509.html

你可能感兴趣的:(django)