zoukankan      html  css  js  c++  java
  • CSIC_716_20200114【Django入门---django中间件、csrf跨站请求伪造、auth认证】

    中间件

    凡是全局相关的功能,都可以考虑使用中间件来实现。例如:全局的身份校验、访问频率校验、访问黑名单、访问白名单。

    中间件总共有5个方法可以使用:

    process_request

    请求从web服务网关接口传到中间件层时,会按照先后顺序依次执行每一个中间件里的process_request方法,遇到没有process_request的中间件会直接跳到下一个中间件。如果不满足其中任何一个就会被拒绝访问。如果process_request返回了一个值HttpResponse对象,那么程序就会从此原路返回,返回的路线要么经过process_response,如果没有process_response也能直接通过HttpResponse返回到前端。

    process_response

    当执行完视图函数后,程序会按照与process_request相反的顺序执行process_response方法。
    该方法必须要有return返回值,否则报错。一般是return response,也可以自己返回一个HttpResponse替换从视图函数传过来的值,外层可以偷换内层传出来的东西

    process_view

    在中间件放行后,执行视图函数之前,会执行process_view

    process_template_response

    他在视图函数执行完之后,process_response执行前执行,他的执行顺序和process_response一样,顺序反向。他触发的条件是:视图函数返回的对象中必须要有render属性对应的render方法。

    process_exception

    在视图函数报错的时候触发,顺序也是反向的。

    上面五个方法的执行顺序:

     

     csrf

    form表单如何通过csrf校验
    你只需要在你的form表单内写一个
    {% csrf_token %}


    ajax如何通过csrf校验

    // 第一种方式 自己手动获取
    {#data:{'username':'jason','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},#}
    // 第二种方式 利用模板语法
    {#data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},#}
    // 第三种 通用方式 引入外部js文件 官网提供的方式
    {% load static %}
    <script src="{% static 'myset.js' %}"></script>
    data:{'username':'jason'}
    

     其中导入Ajax跨站请求伪造的js文件为

     1 function getCookie(name) {
     2     var cookieValue = null;
     3     if (document.cookie && document.cookie !== '') {
     4         var cookies = document.cookie.split(';');
     5         for (var i = 0; i < cookies.length; i++) {
     6             var cookie = jQuery.trim(cookies[i]);
     7             // Does this cookie string begin with the name we want?
     8             if (cookie.substring(0, name.length + 1) === (name + '=')) {
     9                 cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
    10                 break;
    11             }
    12         }
    13     }
    14     return cookieValue;
    15 }
    16 var csrftoken = getCookie('csrftoken');
    17 function csrfSafeMethod(method) {
    18   // these HTTP methods do not require CSRF protection
    19   return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    20 }
    21 
    22 $.ajaxSetup({
    23   beforeSend: function (xhr, settings) {
    24     if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
    25       xhr.setRequestHeader("X-CSRFToken", csrftoken);
    26     }
    27   }
    28 });
    导入Ajax的跨站请求代码

     


    			
    	csrf相关装饰器
    		当我们网站整体都校验csrf的时候 我想让某几个视图函数不校验
    		
    		当我们网站整体都不校验csrf的时候 我想让某几个视图函数校验
    		
    
    		from django.views.decorators.csrf import csrf_exempt, csrf_protect
    		from django.views import View9
    		from django.utils.decorators import method_decorator
    
    		# @method_decorator(csrf_protect,name='post')  # 第二种指名道姓的给类中某个方法装
    		# @method_decorator(csrf_exempt,name='post')  # csrf_exempt 第二种方式不行
    		@method_decorator(csrf_exempt,name='dispatch')  # 可以!!!
    		class MyHome(View):  # APIView
    			# @method_decorator(csrf_protect)  # 第三种 类中所有的方法都装
    			# @method_decorator(csrf_exempt)  # csrf_exempt 第三种方式可以
    			def dispatch(self, request, *args, **kwargs):
    				return super().dispatch(request,*args,**kwargs)
    
    			def get(self,request):
    				return HttpResponse('get')
    			# @method_decorator(csrf_protect)  # 第一种方式
    			# @method_decorator(csrf_exempt)  # csrf_exempt 第一种方式不行
    			def post(self,request):
    				return HttpResponse('post')
    

      

    """
    给CBV加装饰器 推荐你使用模块method_decorator
    我们自己写的装饰器和csrf_protect用法一致
    唯独csrf_exempt是一个特例 只能给dispatch方法装
    """

    auth模块
    django用户相关的自带的功能模块 auth_user表


    如何创建超级用户
    createsuperuser

    模块导入
    from django.contrib import auth
    from django.contrib.auth.models import User


    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)
    

      

    from django.contrib import auth
    from django.contrib.auth.models import User
    def register(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            # User.objects.create(username=username,password=password)  # 不能使用 密码变成明文的了
            # User.objects.create_user(username=username,password=password)  # 不能使用 密码变成明文的了
            # User.objects.create_superuser(username=username,password=password,email='123@qq.com')  # 不能使用 密码变成明文的了
        return render(request,'register.html')
    
    
    def login(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')  # 明文
            # 数据库校验用户名和密码是否正确
            # User.objects.filter(username=username,password=password)
            user_obj = auth.authenticate(request,username=username,password=password)
            """
            用户名密码正确返回的是用户对象
            错误返回None
            """
            # print(res)
            # print(res.username)
            # print(res.password)
            if user_obj:
                # 保存用户登录状态
                # request.session
                auth.login(request,user_obj)
                """
                只要执行了这一句话 之后在任意可以获取到request对象的地方
                都可以通过request.user获取到当前登录的用户对象
                """
                return HttpResponse("登录成功")
        return render(request,'login.html')
    
    
    def get_user(request):
        print(request.user)
        """
        用户登录成功之后 request.user拿到的就是用户对象
        没有登录 获取到的匿名用户
        """
        print(request.user.is_authenticated())
        return HttpResponse("get_user")
    
    # 校验用户是否登录装饰器
    from django.contrib.auth.decorators import login_required
    
    
    # @login_required(login_url='/login/')
    @login_required
    def xxx(request):
        return HttpResponse('xxx页面')
    
    # @login_required(login_url='/login/')
    # @login_required
    @login_required(login_url='/jskahdhsajhdjsadhjk/')
    def yyy(request):
        return HttpResponse('yyy页面')
    
    # @login_required(login_url='/login/')
    @login_required
    def zzz(request):
        return HttpResponse('zzz页面')
    
    
    @login_required
    def set_password(request):
        if request.method == 'POST':
            old_password = request.POST.get('old_password')
            new_password = request.POST.get('new_password')
            # 1 先校验旧密码是否正确
            is_right = request.user.check_password(old_password)
            # print(is_right)
            # 2 再去修改新密码
            if is_right:
                request.user.set_password(new_password)
                request.user.save()  # 一定要save一下  否则无影响
        return render(request,'set_password.html')
    
    
    @login_required
    def logout(request):
        auth.logout(request)
        return HttpResponse('注销成功')
    View Code



    如何扩展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表
    """

  • 相关阅读:
    Java基础知识回顾
    设计模式简单回顾
    数据结构基础知识
    《More Effective C#》读书笔记
    《Effective C#》读书笔记
    《编程匠艺》读书笔记
    《Scrum实战》读书会作业01
    开始一段新的敏捷学习之旅 —— IT帮读书会第4期《Scrum实战》
    【译】别学框架,学架构
    AngularJS学习笔记(1)
  • 原文地址:https://www.cnblogs.com/csic716/p/12194242.html
Copyright © 2011-2022 走看看