zoukankan      html  css  js  c++  java
  • Django之Cookie、Session、CSRF、Admin

    Cookie

    1、获取Cookie:

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

    2、设置Cookie:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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获取(不是绝对,底层抓包可以获取到也可以被覆盖)

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

    1
    2
    <script src='/static/js/jquery.cookie.js'></script>
    $.cookie("list_pager_num"30,{ path: '/' });

    注:

    1、max_age = None 和 expires = None:

    max_age=秒数,表示多少秒数之后失效。

    expires = 时间,表示失效的时间。支持datetime 和 time.time。

    二选一,只要写一个,Django会自动将另一个写上。

    2、path:默认无论哪个url都可以访问到此cookie。

    def cook1(request):
        rep = HttpResponse("cook1")
        rep.set_cookie("k999",123,path="/cook1/")
        rep.set_cookie("k888",123)
        return rep
    
    def cook2(request):
        #request.COOKIES能读到当前url的cookie和全局的cookie
        #能获取到k888,无法获取k999
        print(request.COOKIES)
        return HttpResponse("ok")

    3、domain:只在当前域名生效(http://127.0.0.1:8000/)

    4、secure:以安全的方式传输(HTTPS,加证书进行认证 )

    5、httponly:自己写的cookie只能来回传送,别人不能修改和查看。有局限性

    示例:

    普通cookie:

    from django.shortcuts import render,HttpResponse
    
    def cook(request):
        #拿到所有的cookie
        print(request.COOKIES)
        rep = HttpResponse("ok")
        # 设置普通cookie
        rep.set_cookie("k1",123)  
        return rep

    加密后的cookie:

    默认salt为空

    from django.shortcuts import render,HttpResponse
    
    def cook(request):
        #拿到所有的cookie
        print(request.COOKIES)
        #根据加盐的值来获取cookie
        print(request.get_signed_cookie("k2",None,salt="uuu"))
        rep = HttpResponse("ok")
        #设置加密的cookie,根据salt加密
        rep.set_signed_cookie("k2",222,salt="uuu")
        return rep

     

     

     

    Session

    tornado里面要自定义Session,Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

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

    1、数据库Session

    首先启动数据库:

    python manage.py makemigrations
    
    python manage.py migrate

    views.py:

    def sess(request):
        request.session["k1"] = 123
        return HttpResponse("session")
    def index(request):
        return HttpResponse(request.session["k1"])
    
    def cook(request):
        rep = HttpResponse("cook")
        rep.set_cookie("kk",111)
        return rep

    urls.py:

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^session/', views.sess),
        url(r'^index/', views.index),
        url(r'^cook/', views.cook),
    ]

    这里为了实现设置session的效果,我们先访问cook的url,先设置成功cookie。然后访问index的url,发现获取不了session,这时我们需要访问session的url,访问的同时,就设置了session,当我们再次访问index的时候,就可以看到获取的session的值了。

    注:

    request.session['k1']:获取session,如果没有会报错

    request.session.get('k1',None):获取session,如果没有会返回None

    request.session['k1'] = 123:设置session,如果k1存在就覆盖

    request.session.setdefault('k1',123):设置session,如果存在则不设置

    del request.session["k1"] :只删除k1,随机字符串和其他session值还存在

    request.session.session_key:当前用户随机字符串

    如图:

    注:随机字符串会在客户端浏览器存在,而默认在数据库也会存在,可查看:django_session表

    request.session.clear_expired():将所有Session失效日期小于当前日期的数据删除,默认失效日期是两周(14天)。如果修改失效日期:通过配置文件中SESSION_COOKIE_AGE修改

    更多配置与操作:

    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,默认修改之后才保存(默认)
     
     
     
    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")
    View Code

    2、缓存Session

    默认情况下Django版本的session存在内存里面,使用缓存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

    在本地生成一个文件,把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

    优先在缓存里面获取session,如果没有,就到数据库获取然后放到缓存里

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

    5、加密cookie Session

    这次session就不保存在服务器端了,而是保存在浏览器端,会给session的值加密再发送

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

    查看源码:from django.contrib.sessions.backends import signed_cookies

    扩展:Session用户验证

    1
    2
    3
    4
    5
    6
    7
    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

    跨站请求伪造:CSRF

    一、简介

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

    全局:

      中间件 django.middleware.csrf.CsrfViewMiddleware

    csrf默认情况下只对post提交有效

    实例:

    默认settings.py中间件里面设置了csrf,只要有post提交就要遵循这个规则,所以要在html页面form里面写上{% csrf_token %},并且views.py返回时要用render方法。

    HTML:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/csrf/" method="post">
            {% csrf_token %}
            <input name="n1">
            <input type="submit" value="submit" >
        </form>
    </body>
    </html>

    views.py:

    def csrf(request):
        return render(request,"csrf.html")

    :settings.py里面去掉django.middleware.csrf.CsrfViewMiddleware时,任何地方都用不上csrf,所有的地方都失效

    局部:

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

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

    代码:

    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    #settings.py里面注销了中间件CSRF,如果想把某一个方法必须遵循CSRF,就要写上该装饰器
    #html写{% csrf_token %}
    #函数里面写render
    @csrf_protect
    def csrf(request):
        return render(request,"csrf.html")
    
    
    #settings.py里面就算设置了中间件CSRF,只要写上该装饰器,html就不用写{% csrf_token %},函数里面也不用写render
    @csrf_exempt
    def csrf(request):
        return HttpResponse("CSRF")

    二、应用

    1、普通表单

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

    注:如果返回值使用render_to_response,一定要写上context_instance=RequestContext(request)。原来render_to_response,不具有生成随机字符串的功能,render内部是自动生成该参数。

    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))

    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

     注:ajaxSetup在所有ajax执行之前都要执行该方法,相当于ajax全局配置

    admin

    django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用django admin 则需要以下步骤:

    • 创建后台管理员
    • 配置url
    • 注册和配置django admin后台管理页面

    1、创建后台管理员

    1
    python manage.py createsuperuser

    输入用户名、密码、邮箱。。。

    2、配置后台管理url

    1
    url(r'^admin/', include(admin.site.urls))

    3、注册和配置django admin 后台管理页面

    a、在admin中执行如下配置

    from django.contrib import admin
      
    from app01 import  models
      
    admin.site.register(models.UserType)
    admin.site.register(models.UserInfo)
    admin.site.register(models.UserGroup)
    admin.site.register(models.Asset)

    b、设置数据表名称

    class UserType(models.Model):
        name = models.CharField(max_length=50)
      
        class Meta:
            verbose_name = '用户类型'  #在admin里面不显示UserType,直接显示中文的:用户类型
            verbose_name_plural = '用户类型'  #用户类型后面加个s

    c、打开表之后,设定默认显示,需要在model中作如下配置

    class UserType(models.Model):
        name = models.CharField(max_length=50)
      
        def __unicode__(self):  
            return self.name  #显示name
    from django.contrib import admin
      
    from app01 import  models
      
    class UserInfoAdmin(admin.ModelAdmin):
        list_display = ('username', 'password', 'email') #显示多列
      
      
    admin.site.register(models.UserType)
    admin.site.register(models.UserInfo,UserInfoAdmin)  #配置
    admin.site.register(models.UserGroup)
    admin.site.register(models.Asset)

    d、为数据表添加搜索功能

    from django.contrib import admin
      
    from app01 import  models
      
    class UserInfoAdmin(admin.ModelAdmin):
        list_display = ('username', 'password', 'email')
        search_fields = ('username', 'email')  #输入关键字进行搜索,类似like模糊查询
      
    admin.site.register(models.UserType)
    admin.site.register(models.UserInfo,UserInfoAdmin)
    admin.site.register(models.UserGroup)
    admin.site.register(models.Asset)

    e、添加快速过滤

    from django.contrib import admin
      
    from app01 import  models
      
    class UserInfoAdmin(admin.ModelAdmin):
        list_display = ('username', 'password', 'email')
        search_fields = ('username', 'email')
        list_filter = ('username', 'email')
          
      
      
    admin.site.register(models.UserType)
    admin.site.register(models.UserInfo,UserInfoAdmin)
    admin.site.register(models.UserGroup)
    admin.site.register(models.Asset)
  • 相关阅读:
    现在的代码,贴一下
    2014年七月写过的代码,现在看来,还有待改进呀
    第一次做技术论坛发博文,不知道说点啥
    04-树6. Huffman Codes--优先队列(堆)在哈夫曼树与哈夫曼编码上的应用
    04-树5. File Transfer--并查集
    04-树4. Root of AVL Tree-平衡查找树AVL树的实现
    03-树3. Tree Traversals Again (25)将先序遍历和中序遍历转为后序遍历
    03-树2. List Leaves (25) 二叉树的层序遍历
    二叉树的遍历:先序中序后序遍历的递归与非递归实现及层序遍历
    最大子序列和问题之算法优化
  • 原文地址:https://www.cnblogs.com/0820-zq/p/5808783.html
Copyright © 2011-2022 走看看