Django之Cookie、Session、CSRF、Admin

Cookie

一、獲取Cookie:javascript

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: 後臺控制過時時間

二、設置Cookie:css

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。html

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

注:

一、max_age = None 和 expires = None:java

max_age=秒數,表示多少秒數以後失效。python

expires = 時間,表示失效的時間。支持datetime 和 time.time。jquery

二選一,只要寫一個,Django會自動將另外一個寫上。ajax

二、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")

三、domain:只在當前域名生效(http://127.0.0.1:8000/)django

四、secure:以安全的方式傳輸(HTTPS,加證書進行認證 )瀏覽器

五、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

一、數據庫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

 

二、緩存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

 

三、文件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

 

四、緩存+數據庫Session

優先在緩存裏面獲取session,若是沒有,就到數據庫獲取而後放到緩存裏

數據庫用於作持久化,緩存用於提升效率
 
a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎
 
b. 使用
 
    同上
View Code

 

五、加密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

1、簡介

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

 

2、應用

一、普通表單

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內部是自動生成該參數。

二、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
python manage.py createsuperuser

輸入用戶名、密碼、郵箱。。。

二、配置後臺管理url

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

三、註冊和配置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)
相關文章
相關標籤/搜索