DjangoSCRF、装饰器、auth

1、什么是csrf?

CSRF即跨站请求攻击。简单的说,是攻击者经过一些技术手段欺骗用户的浏览器去访问一个本身之前认证过的站点并运行一些操做(如发邮件,发消息,甚至财产操做(如转帐和购买商品))。由于浏览器以前认证过,因此被访问的站点会绝点是这是真正的用户操做而去运行。python

这就利用了web中用户身份认证验证的一个漏洞:简单的身份验证仅仅能保证请求发自某个用户的浏览器,却不能保证请求自己是用户自愿发出的。

​ 其实能够这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF可以作的事情包含:以你的名义发送邮件;发消息;盗取你的帐号;甚至于购买商品、虚拟货币转帐......形成的问题包含我的隐私泄露以及财产安全。web

大白话总结:本身准备一个拥有默认值(你的银行卡号)的input框,隐藏起来。用户输入转帐的input框,没有name属性。用户发送转帐请求的时候,后端拿到的是你已经准备好的银行卡号,而不是用户输入的。ajax

跨站请求伪造csrf
    钓鱼网站
        本质搭建一个跟正常网站如出一辙的页面
        用户在该页面上完成转帐功能
        
        转帐的请求确实是朝着正常网站的服务端提交
        惟一不一样的在于收款帐户人不一样
        
        给用户书写form表单 对方帐户的input没有name属性
        你本身悄悄提早写好了一个具备默认的而且是隐藏的具备name属性的input
    模拟钓鱼网站

2、csrf原理

从上图可以看出,要完毕一次CSRF攻击,受害者必须依次完毕两个步骤:django

​ 登陆受信任站点A,并在本地生成Cookie。后端

​ 在不登出A的状况下,訪问危急站点B。浏览器

3、如何预防CSRF?

一、提交验证码

​ 在表单中添加一个随机的数字或字母验证码。经过强制用户和应用进行交互。来有效地遏制CSRF攻击。安全

二、Referer Check

​ 检查假设是非正常页面过来的请求,则极有多是CSRF攻击。服务器

三、token验证

(1)在 HTTP 请求中以參数的形式添加一个随机产生的 token,并在服务器端创建一个拦截器来验证这个 token,假设请求中没有 token 或者 token 内容不对,则以为多是 CSRF 攻击而拒绝该请求。cookie

(2)token必须足够随机

(3)敏感的操做应该使用POST,而不是GET。好比表单提交。

四、在HTTP头中本身定义属性并验证

​ 这样的方法也是使用 token 并进行验证。这里并不是把 token 以參数的形式置于 HTTP 请求之中,而是把它放到 HTTP 头中本身 定义的属性里。经过 XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性。并把 token 值放入当中。这样攻克了上种方法在请求中添加 token 的不便。同一时候,经过 XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏,也不用操心 token 会透过 Referer 泄露到其它站点中去。

4、form表单中如何经过csrf校验?

你只须要在你的form表单内写一个  {% csrf_token %}


<form action="" method="post">
    {% csrf_token %}
    old_password:<input type="text" name="old_password">
    new_password:<input type="text" name="new_password">
    <input type="submit">

</form>

5、AJAX如何经过csrf校验?

第一种方式:本身手动获取

$('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            // 第一种方式 本身手动获取
data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},
            success:function (data) {
                alert(data)
            }
        })
    })

第二种方式:利用模板语法

$('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
           // 第二种方式 利用模板语法
            data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},
            success:function (data) {
                alert(data)
            }
        })
    })

第三种方式:通用方式 引入外部js文件 官网提供的方式

$('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
           <script src="{% static 'myset.js' %}"></script>
            success:function (data) {
                alert(data)
            }
        })
    })

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);
    }
  }
});

6、CSRF相关装饰器

一、登陆认证装饰器

使用的时候须要导入:
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator

@csrf_exempt  # 不校验csrf
@csrf_protect # 校验

使用方法

1.在指定函数头上装

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

2.在类名头上指名道姓给某个方法装

@method_decorator(csrf_protect,name='post') 
class MyHome(View): 
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request,*args,**kwargs)
    def post(self,request):
        return HttpResponse('post')
    def get(self,request):
        return HttpResponse('get')

3.类中全部方法都装

class MyHome(View): 
    @method_decorator(csrf_protect)  # 第三种 类中全部的方法都装
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request,*args,**kwargs)
    def post(self,request):
        return HttpResponse('post')
    def get(self,request):
        return HttpResponse('get')

二、校验用户是否登陆装饰器

from django.contrib.auth.decorators import login_required

使用方式:

@login_required(login_url='/index/') 能够传参数,重定向到页面。这是是局部。

@login_required(login_url='/index/')
def yyy(request):
    return HttpResponse('yyy页面')

全局修改参数方式:修改以后,影响全局。局部也能够修改。局部修改就用局部的

在settings.py中添加:LOGIN_URL = '/login/'

7、Django用户相关自带功能模块 auth

一、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)  //删除了session值

二、如何扩展auth_user表?

# 1 利用一对一表关系()
    
    # 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表
        """

相关文章
相关标签/搜索