zoukankan      html  css  js  c++  java
  • django第13天(auth组件,forms组件,中间件,csrf)

    django第13天(auth组件,forms组件)

    auth组件

    -auth组件
    
    -auth是什么?
    -django内置的用户认证系统,可以快速的实现,登录,注销,修改密码....
    
    -怎么用?
    -(1)先创建超级用户:
    -python3 manage.py createsuperuser
    -输入用户名,邮箱(可以不输入),密码,敲回车,这样就创建出一个超级用户
    -也就是在auth_user这个表中插入了一条数据(密码是加密的,所以我不能手动插入)
    
    -(2)验证用户:
    -from django.contrib import auth
    -user = auth.authenticate(request, username=name, password=pwd)
    -相当于在查询:user=models.User.objects.filter(name=name,pwd=pwd).first()
    -如果校验通过,会返回一个user对象,通过判断user对象,校验是否验证成功
    
    -(3)登录
    -auth.login(request,user)
    -其实就是在session中写了一条数据
    
    -(4)一旦登录成功,调了这个函数login(request,user)
    -以后再视图类,函数中的request对象中,就有一个user对象,就是当前登录的用户对象
    -如果没有登录,request.user=AnonymousUser,匿名用户
    
    -(5)注销
    -auth.logout(request)
    -内部:调用了request.session.flush(),删除了登录状态
    
    -(6)登录认证装饰器
    -from django.contrib.auth.decorators import login_required
    -@login_required(redirect_field_name='eee',login_url='/login/')
    -redirect_field_name:修改?后面的key值,
    -login_url:如果没有登录,跳转到的页面
    -可以局部配置
    -可以全局配置(在setting中)
    	# 全局的配置,如果没有登录,跳到这个路由
    	LOGIN_URL='/login/'
    
    -(7)创建用户:
    -from django.contrib.auth.models import User				
    - 创建超级用户和普通用户
    # 不能用create
    # user=User.objects.create(username=name,password=pwd)
    # 创建超级用户
    # user=User.objects.create_superuser(username=name,password=pwd)
    # 创建普通用户
    user=User.objects.create_user(username=name,password=pwd)
    
    -(8)校验密码
    -request.user.check_password(pwd)
    -先拿到用户(可以是登录用户,可以现查)
    
    -(9)修改密码:
    -user.set_password(pwd)
    -user.save()
    -注意:一定要调用save(),否则是不保存的
    
    -(10)is_authenticated()
    -如果通过验证,是true反之false
    
    -(11)其他方法(了解):
    -is_active:禁止登录网站(用户还存在,封号)
    -is_staff:是否对网站有管理权限(能不能登录admin)
    
    -(12)删除用户
    -orm删除
    
    如果想在认证组件上加手机号等其他字段:如何处理
    -(1) 定义一个表模型,跟User一对一管理
    class UserDetail(models.Model):
    phone=models.CharField(max_length=32)
    # 一对一跟auth_user表做关联
    # 如果是从外部引入的表模型,是不能加引号的
    # 如果加引号,只是在当前model找
    user=models.OneToOneField(to=User)
    -(2)定义一个表模型,继承(AbstractUser)
    -from django.contrib.auth.models import AbstractUser
    class UserInfo(AbstractUser):
    # username,password...都有
    phone=models.CharField(max_length=32)
    sex=models.BooleanField()
    -在setting中配置:
    AUTH_USER_MODEL ='app01.UserInfo'
    -做数据库迁移,以后就没有auth_user这个表了,以后认证组件用的表就是UserInfo
    -原来auth中的其他操作:
    -authentication
    -login
    -logout
    -set_password
    ....
    ---一样用,完全一样
    -不一样的地方:
    如果之前用到User这个表模型的地方,都换成UserInfo
    

    forms组件

    forms组件
    -forms是什么?
    就是一个类,可以校验字段(前台传过来的字段)
    
    -怎么用:
        -校验字段功能:
            
     
    from django import forms
    from django.db import models
    
    # Create your models here.
    
    from django.contrib.auth.models import AbstractUser
    
    from django.core.exceptions import ValidationError
    
    -先写一个类,继承Form
    class Myform(forms.Form):
        #min_length属性  检验规范:最小长度
        #max_length
        #error_messages:将违反对应规则的错误信息改为中文
        #label 渲染前台信息的时候,将label设置为中文
        #widget = forms.widgets.PasswordInput(attrs = 'class':'form-control')
        #widget 渲染前台时采用密文的方式,还可以设置样式,attrs = 
        #invalid:格式错误,邮箱
        name = forms.CharField(min_length=3, max_length=8, label="姓名",
                               error_messages={
                                   'min_length': '长度不短于3',
                                   'max_length': '长度不长于8',
                                   'required': '不能为空',
                               })
        pwd = forms.CharField(min_length=3, max_length=8, label="密码",
                              widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}),
                              error_messages={
                                  'min_length': '长度不短于3',
                                  'max_length': '长度不长于8',
                                  'required': '不能为空',
                              })
                                
        email = forms.EmailField(label="邮箱",
                                 error_messages={
                                     'min_length': '长度不短于3',
                                     'max_length': '长度不长于8',
                                     'required': '不能为空',
                                     'invalid': '格式错误'
                                 }         
    

    渲染模板

    -渲染模板
    -第一种方式:(灵活性最高)
    <form action="">
        姓名:{{ myform.name }}
        密码:{{ myform.pwd }}
        邮箱:{{ myform.email }}
        <input type="submit" value="注册">
    </form>
                                 
                                 
    -第二种方式:for循环form对象(用的比较多):
    <form action="" method="post" novalidate>
        {% for obj in myform %}
          <p>{{obj.label }}:{{ obj }}
              <span>{{ obj.errors.0 }}</span>
          </p>
        {% endfor %}
        <input type="submit" value="注册">
        <span>{{ error_msg }}</span>
    </form>		
    			
                                 
    -第三种方式(不建议用):
    <form action="" method="post" >
    {#    {{ myform.as_p }}#}
    {{ myform.as_ul }}
    <input type="submit" value="提交">
    </form>
        
    

    渲染错误信息

    -渲染错误信息
    - myforms有errors
    -属性(name)也有errors
    -错误信息,变成中文:
        - error_messages={'max_length': '最长是8', 'min_length': '最短是3', 'required': '这个必须填','invalid': '不符合邮箱格式'}
        -给input标签指定样式,指定格式:
            -widget=widgets.TextInput(attrs={'class':'form-control'})
            -模板,渲染错误信息:<span>{{ myform.name.errors.0 }}</span>
    
    

    局部钩子

    
    局部校验,只要form中name校验过了,就可以执行到
    #导入validationError
    from django.core.exceptions import ValidationError
    #编写需要增加校验项的字段
    def clean_name(self):
        #取出字段校验通过的信息,用来再进行判断,如果没通过就不会执行到此函数
        name = self.cleaned_data.get('name')
        import re
        pattern = '^d+'
        if re.match(pattern,name):
            raise ValidationError("不能以数字开头")
        return name
    

    全局钩子

    #导入validationError
    from django.core.exceptions import ValidationError
    #一定会被执行,不管前面是否校验通过
    def clean(self):
        pwd = self.cleaned_data.get('pwd')
        re_pwd = self.cleaned_data.get('re_pwd')
        if pwd!=re_pwd:
           raise ValidationError("两次密码不同")#会放在errors的__all__属性里
        return self.cleaned_data
    
    前台
    <form action="" method="post" novalidate>
        <form action="">
        {% for obj in myform %}
          <p>{{obj.label }}:{{ obj }}
              <span>{{ obj.errors.0 }}</span>
          </p>
        {% endfor %}
        <input type="submit" value="注册">
        <span>{{ error_msg }}</span>#放在for循环里,会打多次
        </form>
    </form>
    
    
    def register(request):
        if request.method == "GET":
            myform = Myform()
        if request.method == "POST":
            myform = Myform(request.POST)
            if not myform.is_valid():#判断是否通过验证
               # {'__all__': [ValidationError(['两次密码不同'])]}
            	try:
                	error_msg = myform.errors.as_data().['__all__'][0]#errors.as_data()得到的是字典	
                except:
                    pass
        return render(request,"register.html",locals())
    

    中间件

    ## 中间件
    
    ​```python
    1.中间件是什么:
        请求和响应之间的一道屏障
    2.中间件的作用:
        控制请求和响应
    3.自定义中间件
    
    一.导入类
    from django.utils.deprecation import MiddlewareMixin
    二.定义一个我们自己的中间件(类),继承MiddlewareMixin
    
    from django.utils.deprecation import MiddlewareMixin
    
    class Mymiddle1(MiddlewareMixin):
        def process_request(self,request):
            pass
        
        def process_response(self,request,response):
            pass
    三.在配置文件中注册自定义中间件
    
    MIDDLEWARE = [
        'app01.mymiddle.Mymiddle1'
    ]
    
    ​```
    
    ## 中间件的方法
    
    ​```python
       
        process_request(self,request)
    
        process_view(self, request, callback, callback_args, callback_kwargs)
    
        process_template_response(self,request,response)
    
        process_exception(self, request, exception)
    
        process_response(self, request, response)
    ​```
    
    ## process_request    process_response
    
    ​```python
    
    返回值
    ①process_request 
    如果return HttpResponse对象,直接返回,其后的中间件就不起作用了
    如果return None(默认就是return none) 继续往下走
    ②process_reponse
    必须要return Httpresponse的对象
    
    执行顺序
    中间件的process_request方法是在执行视图函数之前执行的。
    
    当配置多个中间件时,会按照MIDDLEWARE中的注册顺序,也就是列表的索引值,从前到后依次执行的。
    
    不同中间件之间传递的request都是同一个对象
    
    多个中间件中的process_response方法是按照MIDDLEWARE中的注册顺序倒序执行的,也就是说第一个中间件的process_request方法首先执行,而它的process_response方法最后执行,最后一个中间件的process_request方法最后一个执行,它的process_response方法是最先执行。 
    ​```
    
    ## process_view
    
    ​```python
    process_view(self, request, view_func, view_args, view_kwargs)
    
    该方法有四个参数
    
    request是HttpRequest对象。
    
    view_func是Django即将使用的视图函数。 (它是实际的函数对象,而不是函数的名称作为字符串。)
    
    view_args是将传递给视图的位置参数的列表.
    
    view_kwargs是将传递给视图的关键字参数的字典。 view_args和view_kwargs都不包含第一个视图参数(request)
    
    Django会在调用视图函数之前调用process_view方法。
    
    它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。 如果它返回一个HttpResponse对象,Django不会调用适当的视图函数。 它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。
    ​```
    
    ## process_template_response(了解)
    
    ​```python
    该方法对视图函数返回值有要求,必须是一个含有render方法类的对象,才会执行此方法
    
    
    
    class Test:
        def __init__(self,status,msg):
            self.status=status
            self.msg=msg
        def render(self):
            import json
            dic={'status':self.status,'msg':self.msg}
            return HttpResponse(json.dumps(dic))
        
    def index(response):
        return Test(True,'测试')
    
    ​```
    
    ## 中间件的应用场景
    
    ​```python
    1.做ip访问频率的限制
    某些IP访问服务器的频率过高,进行拦截,比如限制每分钟不能超过20次。
    
    
    2.url访问过滤
    
    如果用户访问的是login视图(放过)
    
    如果访问其他视图,需要检测是不是有session认证,已经有了放行,没有返回login,这样就省得在多个视图函数上写装饰器了!
    ​```
    
    
    

    CSRF

    cross site request
    是什么
    攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说这个请求是完全合法的
    原理,你登陆后拿到了服务端的cookie,当你不关闭网站A,打开了黑客网站B,点击了网站B的按钮发请求,请求发到了网站A的服务器,B也带着你的cookie
    
    
    如何防范:
        1.通过refer
        2.加一个随机字符串检验(加载请求的路径里,加载请求体中)
        3.在请求头加字符串校验
    
    
    form表单:{% csrf_token %}
    
    视图函数:request.POST.csrfmiddlewaretoken
    
        
    django中的应用:
        1.中间件不注释
        2.以后发post请求,携带那个随机字符串
        
    
    ajax中的应用:
    属性选择器:
        
        1.data{
         'csrfmiddlewaretoken':
        $('[name = 'csrfmiddlewaretoken']').val()    
        }
        2.data{
            'csrfmiddlewaretoken':'{{csrf_token}}'
        }
        
        3.
        需要导入插件 jquery.cookie.js
        
        从cookie中取,放入请求头
        var token = $.cookie('csrftoken')
       # var token = '{{csrf_token}}'
    
       $.ajax(
       {
           headers:{'X-CSRFToken':token}
       })
    
    

    csrf局部禁用

    导一个装饰器
    from django.views.decorators.csrf import  csrf_exempt,csrf_protect
    
    #局部禁用装饰器
    @csrf_exempt
    #局部保护装饰器
    @csrf_protect
    
    CBV的局部禁用和局部使用
    
    from django.views import View
    from django.utils.decorators import method_decorator
    #2.@method_decorator(csrf_protect,name= 'dispatch')加在类上,标注名称
    class Csrf_disable(View):
        
        #1.@method_decorator(csrf_protect)加在dispatch方法上
        def dispath(self,request,*args,**kwargs):
            res= super().dispatch(request,*args,**kwargs)
    		return res
       
        def get(self,request):
            return 
        
        def post(self,request):
            return
    
    
  • 相关阅读:
    win7 下加载MSCOMCTL.OCX
    getGLES1ExtensionString: Could not find GLES 1.x config!
    IUnknown(TVarData(Params[0]).VPointer) as Range
    win8 VB6打开提示MSCOMCTL.ocx未注册
    服务端接口处理流任务要如何返回?
    flink之kafka生产和消费实战-将生产数据存放到mongodb中
    初识doris的那些基本概念
    bash常见用法
    sonar p3c规则配置
    sonar之gitlab ci 在gradle项目的实践(汉化、branch、 commit提交评论)
  • 原文地址:https://www.cnblogs.com/robert-zhou/p/10570534.html
Copyright © 2011-2022 走看看