CBV添加装饰器 csrf跨站请求伪造 、装饰器 auth模块

CBV添加装饰器 csrf跨站请求伪造 、装饰器 auth模块

 

  • CBV添加装饰器
  • csrf跨站请求伪造
  • csrf相关装饰器
  • Auth模块
    • 只要是跟注册,登录,修改密码,注销,验证是否登录等等

 

  • CBV添加装饰器

    # 1. FBV: function based view    基于函数的视图函数
    # 2. CBV:class based view    基于类的视图函数
    
    1.from django.views import View    #CBV必须继承View
    	class IndexView(View):
            
    2.导入模块
    	from django.utils.decorators import method_decorator
    3.类添加装饰器
    #类添加装饰器
    #方拾2 针对不同方法添加不同的装饰器
    @method_decorator(login_auth,name='get') #某个方法加装饰器 可以指定多个
    @method_decorator(login_auth,name='post') #某个方法加装饰器 这样写的好处 这个方法可以装别的装饰器
    class IndexView(View):
        # @method_decorator(login_auth)     #某个方法饰器  方法1
        #第三种方法 自定义dispatch方法 给这个装一个装饰器 会直接作用于当前类里所有的方法
        def get(self,request):
            return HttpResponse('get方法再此')
        def post(self,request):
            return HttpResponse('post方法再此')
    
  • csrf跨站请求伪造

    钓鱼网站
         '''
         	有一个正规的中国银行网站,我也写了一个跟中国银行网站一模一样的网站,用户不小心来到了我的网站,开始进行转账,前确实转到了中国银行系统,用户的钱也确实少了,但是,被转的用户不是用户想要转的账户
         '''
          如何避免该问题?
        	在渲染form表单的时候,给一个随机的标识,下次提交的时候,后天验证该标识,如果不一样,说明不是我们的页面,直接403, 否则,验证通过
      
    解决:
    	1. 加唯一标识
        <form action="" method="post">
       		 {% csrf_token %} # 生成唯一标识
        </form>
        2、ajax提交
        $('.btn').click(function () {
            $.ajax({
                url:'',
                type:'post',
                // ajax提交,随机字符串也应该提交过去
                第一种方式  利用标签查找页面的随机字符串
    
                data:{
                    'username':'zhang',
                    'csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()},
    
                // 第二种方式 利用模板语法
                data{
                    data:{
                           'username':'zhang',
                          'csrfmiddlewaretoken': '{{ csrf_token }}'},#}
    
                
                    
    
                }
            })
        })
            
            
    ################### 第三方方式 引入一个js文件通用方式 ##############     
    #js静态文件如下   记得在settings配置一下 并引入这个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. 全部都验证,但是就有几个方法不验证
    	2. 全部都不验证,但是,就有几个方法需要验证
    '''
    先引入这两个装饰器
    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    这两个装饰器分别是
        csrf_protect: 需要验证
        csrf_exempt:不需要验证
    #FBV 里面 中间件 如果全部校验 某个函数想不校验可以加@csrf_exempt    ,如果全部不校验  某几个想校验,那么可以加@csrf_protect
    
    
    CBV  符合之前的CBV装饰器的三种
    			#csrf_protect
    # @method_decorator(csrf_protect,name='post')   #csrf_protect 第二种方式可以
    class MyCsrfToken(View):
        @method_decorator(csrf_protect)  # csrf_protect 第三种方式可以
        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 第一种方式可以
        def post(self,request):
            return HttpResponse('post方法再此')
       ############## csrf_exempt########
    # csrf_exempt 只有第三种方法可以
    @method_decorator(csrf_exempt,name='post')   #csrf_exempt 第二种方式不可以
    class MyCsrfToken(View):
    
        @method_decorator(csrf_exempt)  # csrf_protect 第三种方式可以
        def dispatch(self, request, *args, **kwargs):
            return super(MyCsrfToken, self).dispatch(request,*args,**kwargs)
    
    
        def get(self,request):
            return HttpResponse('get方法再此')
    
    
        @method_decorator(csrf_exempt)    #csrf_exempt 第一种方式不可以
        def post(self,request):
            return HttpResponse('post方法再此')
    
  • Auth模块

    '''
    使用auth模块 就全部用auth模块  
    '''
    # 创建django项目之后,执行数据库迁移命令,会生成一堆表,这些表里面有auth开头的,django开头的
    django_session  #存放的服务端session 用户相关数据
    auth_user  #存放的自带的admin页面  登录的管理员用户的账号密码 
    
    
    #登录该后台需要的用户名和密码参考的数据从auth_user表来,并且还要是超级管理员才能登录
    # 1.创建超级管理员
        python3 manage.py createsuperuser
    	会存在auth_user这个表里 密码是密文的
        #创建普通用户
    
    #2.登录
    导入模块
    	from django.contrib import auth
    from django.contrib import auth
    
    def login(request):
        if request.method=='POST':
            username=request.POST.get('username')
            password=request.POST.get('password')
            #拿账号密码去数据库比对
            # 表如何获取
            # 密码如何比对 因为表里密码密文  获取的是明文
            user_obj=auth.authenticate(request,username=username,password=password)
            # print(res)       #符合返回数据对象 重写了__str__ 数据不符合返回None
            # print(res.username)  #可以点
            # print(res.password)
    
            '''
            authenticate 实现了两件事
            1.自动查找auth_user表
            2.自动给密码加密比对
            括号内必须同时传入用户名和密码  不能只传用户名
            user_obj是一个数据对象  他自动写了一个__str__方法 为当前对象的username
            如果不符合返回None
            '''
    
            #判断用户名密码是否正确
            if user_obj:
                #保存用户状态  让他一直是登录状态 操作session表
                auth.login(request,user_obj) #等于 request.session['key']=user_obj
                #只要执行了上面这个方法  就可以在任何地方使用request.user拿到当前登录的对象
                return redirect('/home/')
    
        return render(request,'login.html')
    #3.验证是否登录
    #导入是否登录装饰器
    from django.contrib.auth.decorators import login_required
    
    # login_url 未登录访问这个后面指定的地址 局部配置   还可以全局配置 全局配置后 就没必要加了
    # @login_required  (login_url='/login/')  #该装饰器必须登录才可以访问下面方法
    @login_required
    def home(request):
        # print(request.user)  #拿到的用户对象  没登录拿到匿名用户AnonymousUser
        print(request.user.is_authenticated())  #判断用户是否登录  true登录   false未登录
    
        return HttpResponse('home')
    
    '''
    全局配置和局部配置 都有的情况 局部配置大于全局配置
    全局:不用重复写代码  ,跳转代码固定
    局部:不同的视图函数在没有登录情况下可以跳转到不同页面 
    
    settings.py里面
    #全局配置没有登录跳转到指定页面
    LOGIN_URL='/login/'
    '''
    
    # @login_required  #(login_url='/login/')
    @login_required
    def index(request):
        return HttpResponse('index')
    #4.修改密码
    @login_required
    def set_password(request):
        if request.method=='POST':
            old_password=request.POST.get('old_password')
            new_password=request.POST.get('new_password')
            confirm_password=request.POST.get('confirm_password')
            #校验老密码是否正确
            if request.user.check_password(old_password):
                #校验新密码两次输入是否一致
                if new_password==confirm_password:
                    #写入新密码 不会影响数据库  修改对象的属性
                    request.user.set_password(new_password)
                    request.user.save() #真正操作数据库
    
        return render(request,'set_password.html',locals())
    
    #5.注销
    def loginout(request):
        auth.logout(request)   #等于清空session和cookie request.session.flush()
        return redirect('/login/')
    #6.注册功能
    from django.contrib.auth.models import User  # User就是auth_user表
    def register(request):
        if request.method=='POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            #操作user表
            #创建普通用户create_user
            User.objects.create_user(username=username, password=password)
            #创建超级用户(了解) create_superuser email必须填
        return render(request,'register.html',locals())
    
    
    
    
    
    
    ##############总结方法############
    1. 登录功能
    	#比对用户名密码是否正确
    	user_obj = auth.authenticate(request, username=username, password=password)
        
        # 保存用户信息
    	auth.login(request, user_obj)  # request.session['username'] = user_obj
        	'''
                只要执行了auth.login(request,user_obj),那么,在全局任何地方都可以通过
                request.user拿到用户对象, 封装到request.user
            '''
      2. 验证登录的装饰器
    		from django.contrib.auth.decorators import login_required
      3. 验证是否登录
    	    print(request.user.is_authenticated()) # 验证是否登录成功
     4. 修改密码
    			# 1. 验证老密码是否正确
                is_right = request.user.check_password(old_pwd)
            
            	# 2. 真正的修改数据库
                	request.user.set_password(new_pwd)  # 只是修改了属性,并没有操作数据库
                    request.user.save()  # 这句话才真正操作数据库
     5. 注销功能
    	auth.logout(request)  # request.session.flush()
    6. 注册功能
    	from django.contrib.auth.models import User # User就是auth_user表
    	User.objects.create_user(username=username, password=password)
        #创建超级用户(了解) create_superuser email必须填
    

    扩展auth_user表字段

    # 前提:如果你已经执行了数据库迁移命令,这个时候就不能在扩展auth_user表了
    #       设计表阶段就要明确需不需要扩展表
    from django.contrib.auth.models import User
    1. 扩展auth_user表要继承AbstractUser类
    	auth_user表不会创建出来了 会出现一个新的表
        你的类的名字就是表名
    2. 扩展字段不要动原来的字段,你只需要在继承的类中写你自己想要扩展的字段
    3. 生成一个新表,该表有原来的字段加上你扩展出来的字段
    4. 在settings.py中加个配置:
    	AUTH_USER_MODEL = '应用名.表名'
    5. 扩展表之后,auth_user表就没有了
    
posted @ 2021-12-08 21:36  迪迦张  阅读(21)  评论(0编辑  收藏  举报