zoukankan      html  css  js  c++  java
  • django4

    跨站请求伪造

    一、简介

    django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

    全局:

      中间件 django.middleware.csrf.CsrfViewMiddleware

    局部:

    • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
    • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

    注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

    二、应用

    CSRF,跨站请求伪造
    正常:
    a. 先GET请求:
    页面
    隐藏:input 随机字符串
    b. POST
    数据
    input 随机字符串
    非法:
    b. POST
    数据

    使用:

    Form提交:
    <form action="/icbc.html" method="POST">
    {% csrf_token %}
    <input type='text' name='from' />
    <input type='text' name='to' />
    <input type='text' name='money' />
    <input type='submit' value='转账' />
    </form>

    Ajax提交:
    基于请求体:
    function ajaxSubmit() {
    $.ajax({
    url: "/icbc.html",
    type: 'POST',
    data: {'k1':'v1','k2':'v2','csrfmiddlewaretoken':$('input[name="csrfmiddlewaretoken"]').val() },
    success:function (arg) {
    console.log(arg)
    }
    })
    }

    // 只能写在模板中
    function ajaxSubmit() {
    $.ajax({
    url: "/icbc.html",
    type: 'POST',
    data: {'k1':'v1','k2':'v2','csrfmiddlewaretoken':"{{ csrf_token }}" },
    success:function (arg) {
    console.log(arg)
    }
    })
    }

    function ajaxSubmit() {
    $.ajax({
    url: "/icbc.html",
    type: 'POST',
    data: $('#f1').serialize(),
    success:function (arg) {
    console.log(arg)
    }
    })
    }
    // 以上都是放在请求体中

    基于请求头:
    a. 在cookie中获取csrftoken对应的值 l2kEqQLhR1gH0hh3ioZ1dfxT3iSwjXoKTf7GNFggJZ7E6DROB6k33L7vdqe5lV1v
    b. 发送请求时,放在请求头中也可以

    function ajaxSubmit() {
    $.ajax({
    url: "/icbc.html",
    type: 'POST',
    data: {'k1':'v1','k2':'v2'},
    headers: {"X-CSRFToken": $.cookie('csrftoken')},
    success:function (arg) {
    console.log(arg)
    }
    })
    }

    1、普通表单

    veiw中设置返回值:
      return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))  
         或者
         return render(request, 'xxx.html', data)
      
    html中设置Token:
      {% csrf_token %}
    View Code

    2、Ajax

    对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。

    view.py

    from django.template.context import RequestContext
    # Create your views here.
      
      
    def test(request):
      
        if request.method == 'POST':
            print request.POST
            return HttpResponse('ok')
        return  render_to_response('app01/test.html',context_instance=RequestContext(request))
    View Code

    text.html

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        {% csrf_token %}
      
        <input type="button" onclick="Do();"  value="Do it"/>
      
        <script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
        <script src="/static/plugin/jquery/jquery.cookie.js"></script>
        <script type="text/javascript">
            var csrftoken = $.cookie('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);
                    }
                }
            });
            function Do(){
      
                $.ajax({
                    url:"/app01/test/",
                    data:{id:1},
                    type:'POST',
                    success:function(data){
                        console.log(data);
                    }
                });
      
            }
        </script>
    </body>
    </html>
    View Code

    更多:https://docs.djangoproject.com/en/dev/ref/csrf/#ajax

    Cookie

    cookie是什么?
    - 保存在客户端浏览器上的键值对 {k:v}
    - cookie依附在请求头或响应头中出现
    - 发送请求时,会自动携带自己网站的cookie
    - 应用:
    - 实现登录
    - 投票

    1、获取Cookie:

    request.COOKIES['key']
    request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
        参数:
            default: 默认值
               salt: 加密盐
            max_age: 后台控制过期时间
    View Code

    2、设置Cookie:

    rep = HttpResponse(...) 或 rep = render(request, ...)
     
    rep.set_cookie(key,value,...)
    rep.set_signed_cookie(key,value,salt='加密盐',...)
        参数:
            key,              键
            value='',         值
            max_age=None,     超时时间
            expires=None,     超时时间(IE requires expires, so set it if hasn't been already.)
            path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
            domain=None,      Cookie生效的域名
            secure=False,     https传输
            httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
    View Code

    由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。

    <script src='/static/js/jquery.cookie.js'></script>

    $.cookie("list_pager_num"30,{ path: '/' });
     
    - 使用:
    - 设置:
    response = redirect('/index.html')
    response.set_cookie('uuuuuuuuu',user)
    return response

    key,

    value='',
    max_age=None, # 超时时间
    expires=None, # 超时时间
    path='/', # 访问指定url时,才能读取到cookie
    domain=None, # 当前域名或二级域名
    secure=False, # https
    httponly=False #

    - 获取:
    ck = request.COOKIES.get('uuuuuuuuu')

    Session

    Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

    • 数据库(默认)
    • 缓存
    • 文件
    • 缓存+数据库
    • 加密cookie

    1、数据库Session

    Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
     
    a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
         
        SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
        SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
        SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
        SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
        SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
        SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
        SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)
    View Code
    b. 使用
     
        def index(request):
            # 获取、设置、删除Session中数据
            request.session['k1']
            request.session.get('k1',None)
            request.session['k1'] = 123
            request.session.setdefault('k1',123) # 存在则不设置
            del request.session['k1']
     
            # 所有 键、值、键值对
            request.session.keys()
            request.session.values()
            request.session.items()
            request.session.iterkeys()
            request.session.itervalues()
            request.session.iteritems()
     
     
            # 用户session的随机字符串
            request.session.session_key
     
            # 将所有Session失效日期小于当前日期的数据删除
            request.session.clear_expired()
     
            # 检查 用户session的随机字符串 在数据库中是否
            request.session.exists("session_key")
     
            # 删除当前用户的所有Session数据
            request.session.delete("session_key")
     
            request.session.set_expiry(value)
                * 如果value是个整数,session会在些秒数后失效。
                * 如果value是个datatime或timedelta,session就会在这个时间后失效。
                * 如果value是0,用户关闭浏览器session就会失效。
                * 如果value是None,session会依赖全局session失效策略。
    使用

    2、缓存Session

    a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
        SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
     
     
        SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
        SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路径
        SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名
        SESSION_COOKIE_SECURE = False                             # 是否Https传输cookie
        SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http传输
        SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期
        SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存
     
     
     
    b. 使用
     
        同上
    View Code

    3、文件Session

    a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
        SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
     
     
        SESSION_COOKIE_NAME = "sessionid"                          # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
        SESSION_COOKIE_PATH = "/"                                  # Session的cookie保存的路径
        SESSION_COOKIE_DOMAIN = None                                # Session的cookie保存的域名
        SESSION_COOKIE_SECURE = False                               # 是否Https传输cookie
        SESSION_COOKIE_HTTPONLY = True                              # 是否Session的cookie只支持http传输
        SESSION_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否关闭浏览器使得Session过期
        SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次请求都保存Session,默认修改之后才保存
     
    b. 使用
     
        同上
    View Code

    4、缓存+数据库Session

    数据库用于做持久化,缓存用于提高效率
     
    a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎
     
    b. 使用
     
        同上
    View Code

    5、加密cookie Session

    a. 配置 settings.py
         
        SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
     
    b. 使用
     
        同上
    View Code

    扩展:Session用户验证

    def login(func):
        def wrap(request, *args, **kwargs):
            # 如果未登陆,跳转到指定页面
            if request.path == '/test/':
                return redirect('http://www.baidu.com')
            return func(request, *args, **kwargs)
        return wrap
    View Code

    分页(自定义)

    分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。

    1、设定每页显示数据条数

    2、用户输入页码(第一页、第二页...)

    3、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

    4、在数据表中根据起始位置取值,页面上输出数据


    需求又来了,需要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]

    1、设定每页显示数据条数

    2、用户输入页码(第一页、第二页...)

    3、设定显示多少页号

    4、获取当前数据总条数

    5、根据设定显示多少页号和数据总条数计算出,总页数

    6、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

    7、在数据表中根据起始位置取值,页面上输出数据

    8、输出分页html,如:[上一页][1][2][3][4][5][下一页]

    #!/usr/bin/env python
    # _*_coding:utf-8_*_
    from django.utils.safestring import mark_safe
     
    class PageInfo(object):
        def __init__(self,current,totalItem,peritems=5):
            self.__current=current
            self.__peritems=peritems
            self.__totalItem=totalItem
        def From(self):
            return (self.__current-1)*self.__peritems
        def To(self):
            return self.__current*self.__peritems
        def TotalPage(self):  #总页数
            result=divmod(self.__totalItem,self.__peritems)
            if result[1]==0:
                return result[0]
            else:
                return result[0]+1
     
    def Custompager(baseurl,currentPage,totalpage):  #基础页,当前页,总页数
        perPager=11
        #总页数<11
        #0 -- totalpage
        #总页数>11
            #当前页大于5 currentPage-5 -- currentPage+5
                #currentPage+5是否超过总页数,超过总页数,end就是总页数
            #当前页小于5 0 -- 11
        begin=0
        end=0
        if totalpage <= 11:
            begin=0
            end=totalpage
        else:
            if currentPage>5:
                begin=currentPage-5
                end=currentPage+5
                if end > totalpage:
                    end=totalpage
            else:
                begin=0
                end=11
        pager_list=[]
        if currentPage<=1:
            first="<a href=''>首页</a>"
        else:
            first="<a href='%s%d'>首页</a>" % (baseurl,1)
        pager_list.append(first)
     
        if currentPage<=1:
            prev="<a href=''>上一页</a>"
        else:
            prev="<a href='%s%d'>上一页</a>" % (baseurl,currentPage-1)
        pager_list.append(prev)
     
        for i in range(begin+1,end+1):
            if i == currentPage:
                temp="<a href='%s%d' class='selected'>%d</a>" % (baseurl,i,i)
            else:
                temp="<a href='%s%d'>%d</a>" % (baseurl,i,i)
            pager_list.append(temp)
        if currentPage>=totalpage:
            next="<a href='#'>下一页</a>"
        else:
            next="<a href='%s%d'>下一页</a>" % (baseurl,currentPage+1)
        pager_list.append(next)
        if currentPage>=totalpage:
            last="<a href=''>末页</a>"
        else:
            last="<a href='%s%d'>末页</a>" % (baseurl,totalpage)
        pager_list.append(last)
        result=''.join(pager_list)
        return mark_safe(result)   #把字符串转成html语言
    
    分页实例
    View Code

    总结,分页时需要做三件事:

    • 创建处理分页数据的类
    • 根据分页数据获取数据
    • 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]
  • 相关阅读:
    IE6,IE7 DIV高度技巧(div高度兼容问题)
    QQ在线咨询插件
    Singleton单件 (创建型模式)
    SQL Server ErrorLog 错误日志(如果数据库所占空间变大)
    IE6 div标签height的Bug
    c# 中 Volatile关键字理解
    翻译:SWFObject 2.0官方文档(用来做flash的js)
    已连接到空闲例程的问题解决办法
    Oracle 的一个非常好的触发器例子
    Oracle中表的非常全面的操作
  • 原文地址:https://www.cnblogs.com/onda/p/7474488.html
Copyright © 2011-2022 走看看