美文网首页
rest_framework认证,权限,节流,版本,解析器总结

rest_framework认证,权限,节流,版本,解析器总结

作者: shuffle笑 | 来源:发表于2019-05-07 20:35 被阅读0次

    建立后端项目,model模型,view视图,url路由配置

    这里对应的就是我们写的model模型user用户和token信息表

    一,认证组件

    (1)   设置认证,只有通过的用户才能访问指定的url地址

    (2)   写认证的类父元素是APIview,rest_framework源码dispatch里面调用了封装之后的request,调用initial方法里面调用了perform_authentication方法,返回的是user/auth俩值,我们写认证则要重新定义perform_authentication,根据token来匹配数据库做判断返回相对应的返回.

    (3)写好之后需要在setting文件中配置

    这里键是根据APIview下方设置的中间件来定义的

                 api_settings.DEFAULT_AUTHENTICATION_CLASSES

                 REST_FRAMEWORK = {

    'DEFAULT_AUTHENTICATION_CLASSES'['unitls.authentication.MyOrderAuthentication'],

                 }

    (这里设置的是全局认证),如果是局部认证只需要在view中需要认证的地方写入

                authentication_classes = [这里是自己定义的认证类]

    **注意的是如果开启全局认证用户登录前需要关闭认证则要写入**

                 authentication_classes = []

    注册成功之后要存数据库,用来后面登录做匹配

                    username = request._request.POST.get('username')

                    password = request._request.POST.get('password')

      这里为们要用md5加码生成token然后保存

                  token = md5(username,password)

                  # 将token保存

                    UserToken.objects.update_or_create(

                    user=obj,defaults={'token':token},

                      )

    保存后面登录根据 生成的token来做匹配判断

    二,权限

    (1)   给用户设置权限,只有登录用户并且是指定用户才能访问

    (2)   和认证方法大致相同在initial方法下调用

    self.check_permissions(request),进入到check_permissions函数中发现里面是做一个对象循环判断

                  if not permission.has_permission(request, self):

    #在自定义的Permission中has_permission方法是必须要有的

    #判断当前has_permission返回的是True,False,还是抛出异常

    #如果是True则表示权限通过,False执行下面代码

    #为False的话则抛出异常,当然这个异常返回的提示信息是英文的,如果我们想让他显示我们自定义的提示信息

    #我们重写permission_denied方法即可

                 self.permission_denied(

    #从自定义的Permission类中获取message(权限错误提示信息),一般自定义的话都建议写上,如果没有则为默认的(英文提示)

                    self.permission_denied(

                   request,message=getattr(permission,'message',None)

                    )

    只需要更改message值就行比如

    message ='你不是超级用户,没有权限访问'

    (---------)例如我在下面写了一个判断3表示的是svip用户

                def has_permission(self, request, view):

    """

                          Return `True` if permission is granted, `False` otherwise.

        返回True表示有权限访问,返回False表示没有权限访问"""

                           if request.user.user_type !=3:

                                   return False

                            return True

    ******全局配置

    REST_FRAMEWORK = {

    "DEFAULT_PERMISSION_CLASSES":[自己写权限类的路径]

    }

    三,节流

    有些时候为了对用户的访问频率进行限制和防止爬虫,需要在规定的时间中对用户访问的次数进行限制

    (1),源码入口dispatch--------->>执行认证  self.initial ------->>频率控制self.check_throttles(request)里面做循环判断,

    for  throttlein self.get_throttles():

          if  not throttle.allow_request(request, self):

                    self.throttled(request, throttle.wait())

    如果没有通过会返回 false 执行 self.throttled(request, throttle.wait()),抛出异常---------返回True表示可以继续访问

    def get_throttles(self):

               # 返回访问频率控制的

              return[throttle()  for    throttle   in    self.throttle_classes]--------------->>

    所以说我们需要进行节流限制接口设置类属性

    throttle_class = [ 节流限制的类 ]

    我们需要重写allow_request(request, self) 和 wait 方法

    **全局设置

    REST_FRAMEWORK = {

    "DEFAULT_THROTTLE_CLASSES":{

    'unlogin':'10/m',

     'logined':'3/m'

    }

    这里的unlogin和logined是我们在节流类下面写入----->>类:scope ='logined'

    四,版本

    1,类:在新版本上线,老版本不能直接删除情况下,用到版本控制

    2,  进口dispatch ---->>initial下面有版本控制源码

    version, scheme =self.determine_version(request, *args, **kwargs)

    request.version, request.versioning_scheme = version, scheme

    3,这里调用方法self.determine_version,进入看到

    def determine_version(self, request, *args, **kwargs):

           if self.versioning_classis None:

                     return (None,None)

          scheme =self.versioning_class()

           return (scheme.determine_version(request, *args, **kwargs), scheme)

    (1)versioning_classis是在setting中定义的版本控制类

    (2)versioning_class()进行定义的版本控制类实例化赋值给了scheme

    (3) 最后return中 执行版本控制类中的determine_version方法,返回version,

    4,scheme.determine_version的执行取决与我们所引用的版本控制类是哪一个,我们一般都用URLPathVersioning和QueryParameterVersioning

    导入后点进入URLPathVersioning,里面发现调用is_allowed_version方法,这里做判断是否能访问当前版本

    return((version  is  not  None  and  version == self.default_version) or

    (version in self.allowed_versions))

    到这我们就获取到访问版本的类,回到开始-------------------------------

    version, scheme = self.determine_version(request, *args, **kwargs)

    request.version, request.versioning_scheme = version, scheme

    我们将version 和scheme封装在request中如果我们访问的版本符合要求我们可以通过调用

    request.version, request.versioning_scheme 来获得版本号和控制版本的类

    5,自己定义版本类模块,定义函数determine_version做版本控制配置路由要改变,,,,类:

    url(r"^(?P<version>[v1|v2]+)/userinfo/", UserInfoView.as_view(),name='vvvv')

    6,全局设置

    'DEFAULT_THROTTLE_CLASSES':['unitls.throll.VisitThrottle'],

    #设置版本的参数

    'VERSION_PARAM':'version',

    'DEFAULT_VERSION':'v1',

    'ALLOWED_VERSIONS':['v1','v2'],

    五,解析器

    1,解析器是对我们请求体中的数据进行反序列化、封装 把我们的所有的请求数据都封装在request.data中 在request.data中获取数据

    2,使用

    (1)获取用户请求

    (1)获取用户请求体

    (3)根据用户请求头信息和parase_classes=[...],中的请求头进行比较,匹配上请求头就使用该解析器处理

    (4)解析器从请求体中拿数据进行处理,处理完成之后将结果返回给request.data

    -------------------------------------------------------------------

    要导入模块

    from rest_framework.parsers   import FormParser,  JSONParser

    添加局部认证

    parser_classes = [FormParser, JSONParser]

    (1)然后获取数据,正常的post请求

    浏览器中media_type形式为

    media_type ='application/x-www-form-urlencoded'

    (2)如果这里发送的是json数据则返回null空取不到数据

    我们就可以在request的data中获取数据data = request.data

    相关文章

      网友评论

          本文标题:rest_framework认证,权限,节流,版本,解析器总结

          本文链接:https://www.haomeiwen.com/subject/ezwyoqtx.html