设为首页 收藏本站
查看: 977|回复: 0

[经验分享] 自动化运维Python系列之Django CSRF跨站请求伪造、中间件

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2017-3-15 10:32:26 | 显示全部楼层 |阅读模式
CSRF

CSRF,跨站请求伪造是一种挟持用户在当前已登陆的web站点应用程序上执行非本意的操作攻击方法,简单地说,是攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并执行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。

Django的CSRF中间件验证就可以有效地杜绝此类恶意攻击,原理就是Django在内部会对通过验证请求的客户端再做一次加密验证,该加密方式只有Django自己知道,客户端即使携带session反解密CSRF不成功也会拒绝访问;这是Django生命请求周期中必经的一步,由此我们也可以引出中间件的概念及一般的自定义中间件使用方法

在setting中开启CSRF验证

wKioL1jIANrSCS3cAAHlMg-QgZo113.png.jpg

开启后浏览器携带的CSRF验证信息

wKiom1jIAPzh7dEmAAGFS-c5MIQ295.png.jpg

由于开启了全局CSRF验证,以后我们每提交的一个页面POST请求,Django都会要求验证,所以我们必须在页面加载该配置信息,有2种方式

1)前端页面直接提交

<form action="/login/" method="POST">
    // 在from表单中添加模版信息
    {% csrf_token %}
    <input type="text" name="user" />
    <input type="text" name="pwd" />
    <input type="submit" value="提交" />
</form>

2)ajax提交

$(function(){
    // 这是ajax全局事件 发ajax请求之前做操作
    $.ajaxSetup({
        beforeSend: function(xhr,settings){
            xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'));
        }
    });
  
    $('#btn1').click(function () {
        $.ajax({
            url: '/login/',
            type:"GET",
            data: {'user': 'root', 'pwd': '123'},
            // 在请求头中加入CSRFtoken 如果上面已经设置了ajax全局绑定 就可以省略
            // headers: {'X-CSRFtoken': $.cookie('csrftoken')},
            success:function(arg){
            }
        })
    });
})

后台我们可以通过X-CSRFtoken获取

# print(settings.CSRF_HEADER_NAME)
# HTTP_X_CSRFTOKEN
# X-CSRFtoken

对于在中间件中启用CSRF后,意味着全局view函数都会被要求验证,如果有需求某几个页面views不需要,可以添加下面的装饰器

// 取消CSRF验证保护
@csrf_exempt
def index(request):
  
// 单独开启CSRF验证保护
@csrf_protect
def index(request):

中间件

Django中的中间件,其实是一个类,在请求到来和结束后,Django会根据自己的规则在合适的时机执行中间件中相应的方法,如上面图一我们看到的MIDDLEWARE里面的就是Django中已经注册在使用的中间件

1)自定义中间件

在中间件中我们可以自定义5种方法

// 1)接受请求方法
process_request(self,request)
// 2)接受视图方法
process_view(self, request, callback, callback_args, callback_kwargs)
// 3)判断返回函数是否有render方法
process_template_response(self,request,response)
// 4)异常处理方法
process_exception(self, request, exception)
// 5)回复请求
process_response(self, request, response)

在app同级目录建立中间件目录Middle,新建中间件文件m1.py

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
// 定义class 需要继承MiddlewareMixin
class Row1(MiddlewareMixin):
    def process_request(self,request):
        print('request_row_1')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print('view_row_1')

    def process_response(self, request, response):
        print('process_row_1')
        return response

class Row2(MiddlewareMixin):
    def process_request(self,request):
        print('request_row_2')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print('view_row_2')

    def process_response(self, request, response):
        print('process_row_2')
        return response

在setting中注册中间件,注意我们放置位置,运行程序我们看看Django中间件的运行顺序是什么

wKioL1jIAReT0ItOAAHE37ZW03A230.png.jpg

路由URL配置

urlpatterns = [
    url(r'^test/(?P<nid>\d+)$', views.test),
]

views视图函数配置

def test(request,nid):
    print('view --> ')
    return render(request, 'index.html')

运行结果

wKiom1jIASbji6E8AADYZDsEJEI844.png.jpg

所以中间件的运行过程其实如下图所示

wKioL1jIATbCP_OiAAGk1CYIYvg530.png.jpg

Django收到用户请求后,会依次被中间件处理,先经过request方法,等执行到最后一个中间件,经过一次路由匹配找到view对应的函数,回头去执行各个中间件的view方法,此时请求携带的额外参数被封装在view_func参数中,最后由服务器端views视图函数返回数据,中间件通过reponse传递消息给用户。

此时中间件的作用就很明显了,可以在请求真正到达服务器后端前做相应操作,比如拦截操作

wKiom1jIAUrAgBq1AAGpHHGpuWM681.png.jpg

如果在中间件Row_2中对该请求拦截只需要直接return HttpResponse信息

class Row2(MiddlewareMixin):
    def process_request(self,request):
        print('request_row_2')
        return HttpResponse('row_2_no...')

此时我们看中间件执行过程,请求在Row_2中间件处已经被拦截,并没有达到服务器后端views

wKioL1jIAV2AXZA_AADhwhf_U9Y743.png.jpg

异常处理

如果服务端views函数发生异常,一般Django会直接报错给用户界面,这样对用户来说不够友好,所以我们可以在中间层面对一些异常拦截,并处理

def test(request,nid):
    print('view --> ')
    // 模拟处理异常
    i = int('abc')
    return render(request, 'index.html')

编辑中间件函数

class Row2(MiddlewareMixin):

    ...
    // Row_2中加入异常处理
    def process_exception(self, request, exception):
        if isinstance(exception, ValueError):
            return HttpResponse('数据处理出现异常。。')

界面显示

wKioL1jIAW_yT1MbAAB2g7P3nw0078.png.jpg





运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-351416-1-1.html 上篇帖子: paramiko SSHClient调用sudo权限和执行多条指令的方法 下篇帖子: 自动化运维Python系列之Django信号、缓存操作 中间件
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表