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

2019-05-07  本文已影响0人  shuffle笑

建立后端项目,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

上一篇下一篇

猜你喜欢

热点阅读