zoukankan      html  css  js  c++  java
  • 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表了

  • 相关阅读:
    Redis源码分析(二十一)--- anet网络通信的封装
    leetcode 总结part1
    leetcode String to Integer (atoi)
    leetcode 165. Compare Version Numbers
    leetcode 189. Rotate Array
    leetcode 168. Excel Sheet Column Title
    leetcode 155. Min Stack
    leetcode 228. Summary Ranges
    leetcode 204. Count Primes
    leetcode 6. ZigZag Conversion
  • 原文地址:https://www.cnblogs.com/YGZICO/p/12198766.html
Copyright © 2011-2022 走看看