• Django CSRF与auth模块


    Django CSRF与auth模块

    CSRF

    FORM表单中怎么通过CSRF校验

    只需要在form表单中写一个

    {% csrf_token %}
    

    ajax通过asrf校验有三种方法

    $.ajax({
                url:'',
                type:'post',
                {#data:{'username':'yang'},#}
                //第一种方式 自己手动获取
                {#data:{'username':'yang','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val()},#}
                //第二种方式 利用模板语法
                {#data:{'username': 'yang', 'csrfmiddlewaretoken':'{{ csrf_token }}'},#}
                //第三种方式 通用方式 需要引入外部js文件
                data:{'username':'yang'},
                success:function (data) {
                    alert(data)
                }
            })
    

    第三种需要引入外部js文件,文件中需要书写以下代码

    写一个getCookie方法

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

    将上面的文件配置到你的Django项目的静态文件中,在html页面上通过导入该文件即可自动帮我们解决ajax提交post数据时校验csrf_token的问题,(导入该配置文件之前,需要先导入jQuery,因为这个配置文件内的内容是基于jQuery来实现的)


    CSRF相关装饰器

    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    

    应用场景:

    • 当网站整体都校验csrf的时候,想让某几个视图函数不校验
    • 当网站整体都不校验csrf的时候,想让某几个视图函数校验

    csrf_exempt:不校验

    csrf_protect:校验

    # @csrf_exempt    # 不校验csrf
    @csrf_protect  	# 校验csrf
    def index(request):
        print('我是视图函数index')
    
        def render():
            return HttpResponse('我是index里面的render函数')
    
        obj = HttpResponse('index')
        obj.render = render
        return obj
    

    给FBV装饰,导入后直接加装饰器就行

    但是给CBV加装饰器,有三种方式

    需要导入一个方法,使用这个方法method_decorator(csrf_protect)

    1. 加在CBV视图的某个方法上
    from django.views import View
    from django.utils.decorators import method_decorator
    
    class MyHome(View):
    
        def get(self, request):
            return HttpResponse('get')
    
        @method_decorator(csrf_protect) 	# 第一种方式
        def post(self, request):
            return HttpResponse('post')
    
    1. 直接加在视图类上,但是method_decorator需要传入name关键字参数
    from django.views import View
    from django.utils.decorators import method_decorator
    
    @method_decorator(csrf_protect, name='post')  # 第二种,知名道姓的给类的某个方法装饰
    class MyHome(View):
    
        def get(self, request):
            return HttpResponse('get')
    
        def post(self, request):
            return HttpResponse('post')
    
    1. 加在dispatch方法上

    在匹配类方法之前,都需要dispatch方法分发,所以给该方法装饰,就代表整个类中的方法都是校验或不校验

    from django.views import View
    from django.utils.decorators import method_decorator
    
    class MyHome(View):
    
        @method_decorator(csrf_protect)		# 第三种 类中所有的方法都装
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request,*args,**kwargs)
    
        def get(self, request):
            return HttpResponse('get')
    
        def post(self, request):
            return HttpResponse('post')
    

    CBV中首先执行的就是dispatch方法,所以这么写相当于给get和post方法都加上了登录校验。

    补充

    CSRF Token相关装饰器在CBV只能加到dispatch方法上,或者加在视图类上然后name参数指定为dispatch方法。

    • csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
    • csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
    from django.views import View
    from django.utils.decorators import method_decorator
    
    class MyHome(View):
        @method_decorator(csrf_exempt)
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request,*args,**kwargs)
    
        def get(self, request):
            return HttpResponse('get')
    
        def post(self, request):
            return HttpResponse('post')
    

    or

    from django.views import View
    from django.utils.decorators import method_decorator
    
    @method_decorator(csrf_exempt, name='dispatch')
    class MyHome(View):
        def dispatch(self, request, *args, **kwargs):
            return super().dispatch(request,*args,**kwargs)
    
        def get(self, request):
            return HttpResponse('get')
    
        def post(self, request):
            return HttpResponse('post')
    

    注意:给CBV加装饰器,推荐使用模块method_decorator,csrf_exempt只能给dispatch方法装


    auth模块

    Django用户相关的自带的功能模块

    导入模块

    from django.contrib import auth
    from django.contrib.auth.models import User
    

    auth模块常用方法:

    1.创建用户
    • create()

    虽然可以创建,但是密码是明文,对后面的密码校验修改密码等功能都有影响,所以不推荐使用

    User.objects.create(username='用户名',password='密码',email='邮箱',...)
    
    • create_user()

    auth提供的一个创建新用户的方法,需要提供必要参数(username, password)

    User.objects.create_user(username='用户名',password='密码',email='邮箱',...)
    
    • create_superuser()
    User.objects.create_superuser(username='用户名',password='密码',email='邮箱',...)
    
    2.校验用户名和密码是否正确
    • authenticate()

    提供了用户认证功能,需要username 、password两个关键字参数

    authenticate(username='usernamer',password='password')
    

    注意:

    • 认证成功(用户名和密码正确有效),便会返回一个 User 对象
    • 认证失败(用户名和密码不正确),便会返回一个 None
    3.保存用户登录状态(session)
    • login()

    可以实现一个用户登录的功能,需要一个HttpRequest对象,以及一个经过认证的User对象

    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)
            """
            用户名密码正确返回的是用户对象
            错误的话返回的是None
            """
            if user_obj:
                auth.login(request, user_obj)
                return HttpResponse('登录成功')
        return render(request, 'login.html')
    

    只要执行了这个方法,之后在任意可以获取到request对象的地方,都可以通过request.user获取当前登录的对象

    4.判断是否登录以及获取当前登录用户对象
    • is_authenticated()

    用来判断当前请求是否通过了认证

    request.user.is_authenticated()	# 返回布尔值
    
    • request.user

    获取登录用户对象

    5.登录装饰器
    • login_required()

    auth 给我们提供的一个装饰器工具

    from django.contrib.auth.decorators import login_required
    
    @login_required()
    def is_login(request):
        pass
    

    若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' 并传递当前访问url的绝对路径 (登陆成功后,会重定向到该路径).

    可以自定义登录的URL,在settings.py文件中通过LOGIN_URL进行修改

    # 全局配置:
    LOGIN_URL = '/login/'  # 这里配置成你项目登录页面的路由
    # 局部配置:
    @login_required(login_url='/login/')
    

    若两者都配置了,优先执行局部的配置

    6.判断密码是否正确
    • check_password()

    auth提供的一个检查密码是否正确的方法,需要传入当前请求用户的密码,返回布尔值

    is_right = request.user.check_password(old_password)
    
    7.修改密码
    • set_password()

    auth 提供的一个修改密码的方法,接收要设置的新密码

    注意:一定要调用user.save方法保存

    user.set_password(password='')
    user.save()
    

    修改密码的例子

    @login_required()
    def set_password(request):
        if request.method == 'POST':
            old_password = request.POST.get('old_password')
            new_password = request.POST.get('new_password')
            is_right = request.user.check_password(old_password)# 判断旧密码是否正确
            print(is_right)
            if is_right:
                request.user.set_password(new_password)	# 设置新密码
                request.user.save() # save保存
        return render(request, 'set_password.html')
    
    8.注销功能
    • logout()

    需要一个request参数,没有返回值

    当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错

    @login_required()
    def logout(request):
        auth.logout(request)
        return HttpResponse('注销成功')
    

    扩展默认的auth_user表

    我们可以通过继承内置的AbstractUser 类,来定义一个自己的Model类,这样既能根据项目需求灵活的设计用户表,又能使用Django强大的认证系统

    利用类的继承

    from django.contrib.auth.models import User,AbstractUser
    
    class UserInfo(AbstractUser):
        phone = models.CharField(max_length=11, null=True)
        avatar = models.FileField()
        
        def __str__(self):
            return self.username
    

    注意:

    按上面的方式扩展了内置的auth_user表之后,要在settings.py中告诉Django,我现在使用我新定义的UserInfo表来做用户认证。

    写法如下:AUTH_USER_MODEL = '应用名.表名'

    # 引用Django自带的User表,继承使用时需要设置
    AUTH_USER_MODEL = "app名.UserInfo"
    

    再次注意:

    一旦我们指定了新的认证系统所使用的表,我们就需要重新在数据库中创建该表,而不能继续使用原来默认的auth_user表了

  • 相关阅读:
    scrapy爬虫框架学习
    python:面向对象—— __slots__来限制实例的属性命名范围
    列表list 的常用操作
    python replace()用法
    python 字符串 空字符串 len()
    python 字符串 编码问题
    python中语句、函数、类、模块、包之间的关系
    matplotlib 绘制正玄余玄曲线
    Es6/CommonJs/AMD模块系统的差异以及用法
    BOM和DOM的区别
  • 原文地址:https://www.cnblogs.com/YGZICO/p/12198766.html
Copyright © 2020-2023  润新知