django 的中间件 csrf

Require a present and correct csrfmiddlewaretoken for POST requests that have a CSRF cookie, and set an outgoing CSRF cookie.

This middleware should be used in conjunction with the {% csrf_token %}

template tag.

  • django 的中间件是基于 post 的请求,当post 请求到来的时候 在csrftoken 中间件中执行 process_view 验证 token的正确性,如果验证失败,则返回forbidden 提示给用户。

  • 我们可以让中间件不起作用,首先第一种方法是在配置文件中的settings中注释掉cscftoken的中间件,这样其实存在安全隐患

  • 其次我们可以在我们不需要验证csrftoken的视图view中加装饰器来使我们的视图函数免予csrftoken的校验,使用如下:

from django.shortcuts import render, HttpResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt, csrf_protect # csrf_token 单独示例
from django.utils.decorators import method_decorator # 基于函数的使用
@csrf_exempt
def index(request): # what you want you view do in this
return HttpResponse("index") # 基于类的方式 2-1
@method_decorator(csrf_exempt, name="dispatch")
class StudentView(View):
#方式 2-1
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
# do something before diaspatch
ret = super(StudentView, self).dispatch(request, *args, **kwargs)
#do somethig after dispatch
return ret
def get(self, request, *args, **kwargs):
return HttpResponse("GET") def post(self, request, *args, **kwargs):
return HttpResponse("POST")

django 的CBV模式

django 中cbv模式中,已类来接受一个请求的到来,通过类继承 view 类

通过父类的dispatch 方法通过反射 进行请求方法的分发。我们也可以在继承父类的dispatch 方法 来自定制自己的一些操作,rest-framework 也是基于这个实现的,因此我们先看看下他的源码部分:

首先是url中的配置:

urlpatterns = [
re_path('^student/$', views.StudentView.as_view()),
re_path('^dog/$', views.DogView.as_view()),
]

当请求到来的时候,执行as_view() 方法让我们来看下 as_view()做了啥:

    def as_view(cls, **initkwargs):
"""Main entry point for a request-response process."""
.......
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs) # 看这里执行了View的dispatch 方法
view.view_class = cls
view.view_initkwargs = initkwargs # take name and docstring from class
update_wrapper(view, cls, updated=()) # and possible attributes set by decorators
# like csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
return view

再来看看 view类的dispatch 方法:注意可定制的操作前面已经给出

    def dispatch(self, request, *args, **kwargs):
# 这里的self. http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
if request.method.lower() in self.http_method_names:
# 通过反射找到对应的方法
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)

rest_framework 的解读

首先 rest_framework 是为了遵循RESTful 规范而诞生的框架;

那我们首先需要知道什么是RESTful 规范

  • REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”

  • REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态

  • REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”

  • 所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性

  • 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)

接下来让我们了解下他的API设计规范

  • 1、在url接口中推荐使用Https协议,让网络接口更加安全(Https是Http的安全版,即HTTP下加入 SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL(安全套接层协议))

  • 2、url中可以体现这是个API接口 域名规范

https://api.example.com 尽量将API部署在专用域名(会存在跨域问题)

https://example.org/api/ API很简单

  • 3、url中还可以体现版本号,不同的版本可以有不同的接口,使其更加简洁,清晰

URL,如:https://api.example.com/v1/

请求头跨域时, 引发发送多次请求

  • 4、restful 提倡面向资源编程,所以在url接口中尽量要使用名词,不要使用动词

https://api.example.com/v1/zoos

https://api.example.com/v1/animals

https://api.example.com/v1/employees

  • 5、此外url中还可以添加条件去筛选匹配

过滤,通过在url上传参的形式传递搜索条件

https://api.example.com/v1/zoos?limit=10:指定返回记录的数量

https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置

https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数

https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序

https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件

  • 6、可以根据Http不同的method,进行不同的资源操作(5种方法:GET / POST / PUT / DELETE

    / PATCH)

GET :从服务器取出资源(一项或多项)

POST :在服务器新建一个资源

PUT :在服务器更新资源(客户端提供改变后的完整资源)

PATCH :在服务器更新资源(客户端提供改变的属性)

DELETE :从服务器删除资源

  • 7、响应式应该包含状态码
200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。 更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
  • 8、应该有返回值,而且格式为统一的json格式
  • 9、应该返回错误信息
  • 10、返回结果中要提供帮助链接,即API最好做到Hypermedia

django的 rest_framework 组件的使用

1.首先我们的视图需要时候基于cbv的模式,我们的类需要继承rest_framework的view的 APIView 父类

如下:

class DogView(APIView):
def get(self, request, *args, **kwargs):
return HttpResponse("GET") def post(self, request, *args, **kwargs):
return HttpResponse("POST")

接下来让我们研究下APIView的dispath 方法:

    def dispatch(self, request, *args, **kwargs):
"""
`.dispatch()` is pretty much the same as Django's regular dispatch,
but with extra hooks for startup, finalize, and exception handling.
"""
self.args = args
self.kwargs = kwargs
# 对原生的request 加工(丰富)
""""
Request(
request,parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context)
原生的request = request._request
"""
# 首先是对原生的request进行了加个处理
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?

我们来看下 self.initialize_request 这个方法实现方法

  def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
parser_context = self.get_parser_context(request)
# self.get_authenticators() seteings配置的一个列表
# authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
# 对原生的request第二次加工
return Request(
request,
# 封装了解析器类
parsers=self.get_parsers(),
# 封装了用户用户认证的类
authenticators=self.get_authenticators(),
# url后缀名的显示方式 ex--> .json
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
1.首先是用户认证 的解析

在讨论源码之前我先rest_framework配置放在这里(后面需要修改的会加上去):

# 可以看这里

from rest_framework import settings 

# List of settings that may be in string import notation.
IMPORT_STRINGS = (
'DEFAULT_RENDERER_CLASSES',
'DEFAULT_PARSER_CLASSES',
'DEFAULT_AUTHENTICATION_CLASSES',
'DEFAULT_PERMISSION_CLASSES',
'DEFAULT_THROTTLE_CLASSES',
'DEFAULT_CONTENT_NEGOTIATION_CLASS',
'DEFAULT_METADATA_CLASS',
'DEFAULT_VERSIONING_CLASS',
'DEFAULT_PAGINATION_CLASS',
'DEFAULT_FILTER_BACKENDS',
'DEFAULT_SCHEMA_CLASS',
'EXCEPTION_HANDLER',
'TEST_REQUEST_RENDERER_CLASSES',
'UNAUTHENTICATED_USER',
'UNAUTHENTICATED_TOKEN',
'VIEW_NAME_FUNCTION',
'VIEW_DESCRIPTION_FUNCTION'
)

封住完request之后接下来我们看看后面的源码

  # 进行一系列的认证
#初始化进入验证,下面来看看initial 这个函数做了啥
self.initial(request, *args, **kwargs)
#--------------------------------------------------
def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs)
....... ## 版本的控制的
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme # 认证
self.perform_authentication(request) # 权限验证
self.check_permissions(request) # 访问频率
self.check_throttles(request)

接下来讨论 认证方法

self.perform_authentication(request)源码:

View 类
def perform_authentication(self, request):
"""
Perform authentication on the incoming request. Note that if you override this and simply 'pass', then authentication
will instead be performed lazily, the first time either
`request.user` or `request.auth` is accessed.
"""
request.user Request 类 def _authenticate(self):
"""
Attempt to authenticate the request using each authentication instance
in turn.
"""
# 遍历 setting defaults 的列表 的
"""
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication' """
# 执行每个self.authenticators类中的认证类方法:
for authenticator in self.authenticators:
try:
# 返回值有三种
"""
1.返回user 与 token 对象(认证成功)
2.返回None(不做处理,交个下一个)
3.抛出认证异常(认证失败)
"""
user_auth_tuple = authenticator.authenticate(self)
except exceptions.APIException:
self._not_authenticated()
raise if user_auth_tuple is not None:
self._authenticator = authenticator
self.user, self.auth = user_auth_tuple
return self._not_authenticated()

认证类的写法:

# Lower 写法
class MyBasicAuthentication(object): def authenticate(self, request):
token = request._request.GET.get("token")
if token:
return ("alex",None) raise exceptions.AuthenticationFailed("failed") def authenticate_header(self, val):
pass
"""我们可以继承他的类"""
# 基于用户token的认证
from rest_framework.authentication import BasicAuthentication
默认的几种用户认证类 自己写的可以继承BasicAuthentication
1.一中是自己定义类然后在view视图中这要表达:
authentication_classes=[ yourauthclass, ]
2.或者全局配置 REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":[.......]
}

接下来是用户权限的控制 这个比较简单直接上rest的自带的几个权限验证的源码类自己研究:

from rest_framework.permissions import BasePermission

class BasePermission(object):
"""
A base class from which all permission classes should inherit.
"""
def has_permission(self, request, view):
"""
Return `True` if permission is granted, `False` otherwise.
"""
return True # 这个力度更加细致对于每个用户的管理,后面会将
def has_object_permission(self, request, view, obj):
"""
Return `True` if permission is granted, `False` otherwise.
"""
return True

django rest_framework 框架的使用的更多相关文章

  1. Python之Django rest_Framework框架源码分析

    #!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_fram ...

  2. django rest_framework 框架的使用02

    rest_framework 访问频率的限制(节流) 对于用户访问频率的显示,rest_framework 也有自己的类进行约束 先来一个自己的基于它的类的节流类的限制 class VisitCont ...

  3. django rest_framework 框架的使用03

    rest_framework的 数据解析器 首先需要知道前端发给后端的数据格式头有哪些: media_type = 'application/json' media_type = 'applicati ...

  4. Django rest_framework 实用技巧

    前言: 最近工作中需要用到Django rest_framework框架做API, 边学边写,记录了一些实际工作中需要用到的功能,不是很全也不系统,以后需要什么功能可以在这查询. 后续还会更新其它的用 ...

  5. Python之Django rest_Framework(2)

    实例化: v1 = ["view.xxx.path.Role","view.xxx.path.Group",] 可以循环,循环出来的每一个不能实例化 如果把v1 ...

  6. python之Django rest_framework总结

    一.rest api    a.api就是接口         如: - http://www.oldboyedu.com/get_user/                - http://www. ...

  7. rest_framework框架下的Django声明和生命周期

    rest_framework框架下的Django声明和生命周期 Django声明周期(request) 客户端发起请求 请求经过wsgi wsgi: 是一个协议----web服务网关接口,即在web服 ...

  8. Python之Django rest_Framework(3)

    补充:  为什么要前后端分离:       a.因为前端它有自己框架,这样它的效率就非常高       b.不做前后端分离,公司如果既有客户端,又有app这种情况下你就的写两遍 django rest ...

  9. rest_framework框架

    rest_framework框架的认识 它是基于Django的,帮助我们快速开发符合RESTful规范的接口框架. 一  路由 可以通过路由as_view()传参 根据请求方式的不同执行对应不同的方法 ...

随机推荐

  1. Rails Guide--Working with JavaScript in Rails; 如何把jquery转化为原生js

    1 An Introduction to Ajax 打开网页的的过程也叫:request response cycel. JavaScript也可以request然后parse the respons ...

  2. supervisor进程管理工具

    Supervisor 一个python写的进程管理工具,用来启动.关闭.重启进程,可以同时控制多个进程. 安装: pip install supervisor 配置: 通过配置文件来满足自己的需求 配 ...

  3. hdu4965矩阵快速幂

    这题不能直接按常规做啊,因为数组根本就开不下,转换思维A(B*A)^(n*n-1)B 这样的话数组B*A就是10*10了,然后快速幂就行了 刚开始数组都开小了,tle,还找了半天bug...还有就是定 ...

  4. hdu2177威佐夫博弈

    输的话输出0,赢就输出1并且输出第一步走后的数目 威佐夫博弈判断胜负 原理及常见题型求法: http://blog.csdn.net/y990041769/article/details/216940 ...

  5. Dubbo原理简介、与Zookeeper整合利用

    官方文档:http://dubbo.io/books/dubbo-user-book/ Dubbo的简单介绍 Dubbo是一个分布式服务框架,架构如图: 节点角色说明: Provider: 暴露服务的 ...

  6. 002——数组(二)each() list() implode() explode() in_array()

    <?php /** * 数组(二)each() list() implode() explode() in_array() */ /*implode() 把数组拆分成字符串 * explode( ...

  7. fcntl 改变描述符属性

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  8. openfalcon源码分析之transfer

    本节内容 transfer功能 transfer接收数据来源 transfer数据去向 transfer的一致性hash transfer的一致性hash key的计算 transfer源码分析 2. ...

  9. L203 词汇题

    Conditions for the growth of this plant are optimum in early summer.we will live as free people, not ...

  10. memcache+tomcat7.0.37+nginx实现session共享

    一.session工作原理 由于http是无状态的协议,当我们访问了页面A,然后访问页面B,http无法确定这2个页面的访问是来自同一个人.因此,我们要用cookie或session来跟踪用户,根据授 ...