django中间件,基于django中间件的重要编程思想,csrf跨站请求伪造

django中间件

'''
django中间件是django的门户
1、请求来的时候需要先经过中间件才能到达真正的django后端
2、响应走的时候最后也需要经过中间件才能发送出去

django自带七个中间件


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



class SessionMiddleware(MiddlewareMixin):
    def process_request(self, request):
        session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
        request.session = self.SessionStore(session_key)
    def process_response(self, request, response):
        return response
     

class CsrfViewMiddleware(MiddlewareMixin):
    def process_request(self, request):     
            request.META['CSRF_COOKIE'] = csrf_token
    def process_view(self, request, callback, callback_args, callback_kwargs)       
        return self._accept(request)
    def process_response(self, request, response):     
       return response

    
    class AuthenticationMiddleware(MiddlewareMixin):
    def process_request(self, request):       
        request.user = SimpleLazyObject(lambda: get_user(request))
        
'''
django支持程序员自定义中间件并且暴露给程序员五个可以自定义的方法
1、必须掌握
process_request

process_response

2、了解
process_view

process_template_response

process_exception
'''

如何自定义中间件

'''
1、在项目名称或者应用下创建一个任意名称的文件夹
2、在该文件内创建一个任意名称的py文件
3、在该py文件内需要书写类(这个类必须继承MiddlewareMixin)
	然后再这个类里面就可以自定义五个方法了
	(需要几个就写几个)
4、需要将类的路径以字符串的形式注册到配置文件中才能生效


    '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',
    '自己写的中间件路径1',
'''

1、必须掌握
process_request(self,request)
    1、请求来的时候需要经过某一个中间件里面的process_request方法
    结束的顺序是按照配置文件中注册的中间件从上往下的顺序依次执行
    2、如果中间件里面没有定义该方法,那么直接跳过执行下一个中间件
    3、如果该方法返回了HttpResponse对象个,那么请求将不再继续往后执行
    而是直接原路返回(校验失败不允许访问)
    process_request方法就是用来做全局相关的所有限制功能

process_response(self,request,response)
	1、响应走的时候需要经过每一个中间件里面的process_resopnse方法
    该方法有两个额外的参数request,response
    2、该方法必须返回也给HttpResponse对象
    	1、默认返回的就是形参response
        2、你也可以返回自己的(HttpResponse对象)
    3、顺序是按照配置文件中注册了的中间件从下往上依次经过
    如果你没有定义,直接跳过执行下一个
    
    #只要是形参带有response的方法,那么该方法就必须返回response或者HttpResponse对象
    
    研究如果在第一个process_request方法就已经返回HttpResponse对象,那么响应走的时候就是经过所有的中间件里面的process_response还是其他情况
    是其他情况
    	就是会直接走同级别的process_response返回
        
    flask框架也有类似中间件但是它的规律:只要是返回数据了就必须经过所有中间件里面类似于process_response方法
2、了解
process_view
	路由匹配成功之后执行视图函数之前,会自动执行中间件里面的该方法
    顺序是按照配置文件中注册的中间件从上往下的顺序依次执行

process_template_response
	返回的HttpResponse对象有render属性的时候才会触发
    顺序是按照配置文件中注册的中间件从下往上的顺序依次执行

process_exception
	当视图函数中出现异常的情况下触发
    顺序是按照配置文件中注册了的中间件从下往上依次经过

csrf跨站请求伪造

"""
钓鱼网站
	我搭建一个跟正规网站一模一样的界面(中国银行)
	用户不小心进入到了我们的网站,用户给某个人打钱
	打钱的操作确确实实是提交给了中国银行的系统,用户的钱也确确实实减少了
	但是唯一不同的时候打钱的账户不适用户想要打的账户变成了一个莫名其妙的账户

大学英语四六级
	考之前需要学生自己网站登陆缴费

内部本质
	我们在钓鱼网站的页面 针对对方账户 只给用户提供一个没有name属性的普通input框
	然后我们在内部隐藏一个已经写好name和value的input框

如何规避上述问题
	csrf跨站请求伪造校验       ('django.middleware.csrf.CsrfViewMiddleware')
		网站在给用户返回一个具有提交数据功能页面的时候会给这个页面加一个唯一标识
		当这个页面朝后端发送post请求的时候 我的后端会先校验唯一标识,如果唯一标识不对直接拒绝(403 forbbiden)如果成功则正常执行	
"""

如何符合校验

#form表单如何符合校验
<form action="" method="post">
    {% csrf_token %}  #记得不要注释掉settings里面的csrf
    <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>


#Ajax如何符合校验
{% load static %}       
<script src="{% static 'js/mysetup.js' %}"></script>   #这两行是方式三才有的代码
<script>
    $('#d1').click(function(){
        $.ajax({
            url:'',
            type:'post',
            //第一种方式
<!--            data:{'username':'lz','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()},-->
            //第二种方式
<!--                data:{'username':'lz','csrfmiddlewaretoken':'{{csrf_token}}'},-->
            //第三种方式
                    data:{'username':'lz'},
            success:function(){

            }
        })
    })
#其中方式3的js代码
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');

function csrfSafeMethod(method) {
  // these HTTP methods do not require CSRF protection
  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

$.ajaxSetup({
  beforeSend: function (xhr, settings) {
    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
      xhr.setRequestHeader("X-CSRFToken", csrftoken);
    }
  }
});

csrf相关装饰器

"""
1.网站整体都不校验csrf,就单单几个视图函数需要校验
2.网站整体都校验csrf,就单单几个视图函数不校验
"""
from django.views.decorators.csrf import csrf_protect,csrf_exempt
from django.utils.decorators import method_decorator
"""
csrf_protect  需要校验
    针对csrf_protect符合我们之前所学的装饰器的三种玩法
csrf_exempt   忽视校验
    针对csrf_exempt只能给dispatch方法加才有效
"""
# @csrf_exempt
# @csrf_protect
def transfer(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        target_user = request.POST.get('target_user')
        money = request.POST.get('money')
        print('%s给%s转了%s元'%(username,target_user,money))
    return render(request,'transfer.html')



from django.views import View

# @method_decorator(csrf_protect,name='post')  # 针对csrf_protect 第二种方式可以
# @method_decorator(csrf_exempt,name='post')  # 针对csrf_exempt 第二种方式不可以
@method_decorator(csrf_exempt,name='dispatch')
class MyCsrfToken(View):
    # @method_decorator(csrf_protect)  # 针对csrf_protect 第三种方式可以
    # @method_decorator(csrf_exempt)  # 针对csrf_exempt 第三种方式可以
    def dispatch(self, request, *args, **kwargs):
        return super(MyCsrfToken, self).dispatch(request,*args,**kwargs)

    def get(self,request):
        return HttpResponse('get')

    # @method_decorator(csrf_protect)  # 针对csrf_protect 第一种方式可以
    # @method_decorator(csrf_exempt)  # 针对csrf_exempt 第一种方式不可以
    def post(self,request):
        return HttpResponse('post')

重要思想

__init__文件

import settings
import importlib
def send_all(content):
    for path_str in settings.NOTIFY_LIST:   #'notify.email.Email'
        module_path,class_name = path_str.rsplit('.',maxsplit=1)
        #module_path='notify.email'   class_name='Email'
        #1、利用字符串导入模块
        module = importlib.import_module(module_path)    #from notify import email
        #2、利用反射获取类型
        cls = getattr(module,class_name)   #Email,QQ,Wechat
        #3、生成类的对象
        obj = cls()
        #4、利用鸭子类型直接调用send方法
        obj.send(content)

settings文件

NOTIFY_LIST=[
    'notify.email.Email',
    'notify.qq.QQ',
    'notify.wechat.Wechat',
    'notify.msg.Msg',
]

start文件

import notify

notify.send_all('你好呀')

功能模块

class Wechat(object):
    def __init__(self):
        pass
    def send(self,content):
        print('微信通知%s'%content)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值