django-cookie和session
阿新 • • 發佈:2018-11-22
一、cookie
寫cookie和session之前,先說說http協議 它是:請求-->響應的模式,必須瀏覽器(客戶端)向伺服器發出請求之後,伺服器才會響應回你了 無狀態:就是因為這點才會有cookie這些的由來,無狀態就是你的上一次請求,本次請求,下一次請求 都是毫無關聯的,就好比你撥打人工服務(發出一個請求),下一次你再撥打人工服務(再一次請求), 她會知道你是誰嗎? 無連線:意思就是你發出請求,伺服器響應你了,同時會立馬關閉此次連結。 現在我們訪問某些網站,比如TB網,B站,你在上面登陸了賬號,下次再訪問的話,還是你自己資訊在那裡,不是說http協議 是無狀態的嗎?那我下一次訪問伺服器就會知道是我在訪問網站呢?這就是cookie的作用了。 你在訪問一個網站,並且登陸了賬號,它的伺服器會為你這次請求生成一個cookie並且響應回你,你的瀏覽器就會儲存起來, 下一次再訪問該網站的時候,會把這個cookie帶上(放在請求頭中),這樣服務端後臺拿到你的cookie,就知道你的身份,並 把你的身份資訊也返回到你的網頁。這個cookie就相當於你的身份標誌了。 一個瀏覽器可以儲存多個cookie?那訪問網頁的時候,會把所有的cookie都帶上?肯定不會這樣的,你訪問特定的網站,瀏覽 器內部會幫你處理,帶上相應的cookie,不會帶上其他網頁的cookie。這樣也可以降低你的安全風險。 在django中怎麼去用呢 對cookie操作,無非就是增加,刪除,獲取這些,我們在HttpResponse這個物件中操作 那麼,我能不能操作 render redirect JsonResponse這些呢? 答案是可以的,上面的最終都是返回的是HttpResponse物件 obj= HttpResponse('ok') obj.set_cookie() #cookie是一個鍵值對, 原始碼: set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False): 上面這個set_cookie的原始碼,key,value這兩個引數不用講了把,對應的鍵值對的兩個值 max_age ----> 代表過期時間,是None的話,cookie會保持到瀏覽器關閉,以s最為單位 expires=None ----> 傳一個時間物件過去,也是代表過期時間 path='/'----> 代表cookie生效的路徑,'/'代表該伺服器中的所有路由都能生效,都會攜帶上 domain=None ----> cookie生效的域名 secure=False ----> 瀏覽器將通過https來回傳cookie httponly=False ----> 只能http協議傳輸,無法被JavaScript獲取 # 其實記得話只需記得過期時間,和前面那兩個引數,一個key,一個value obj.set_signed_cookie 原始碼: def set_signed_cookie(self, key, value, salt='', **kwargs): value = signing.get_cookie_signer(salt=key + salt).sign(value) return self.set_cookie(key, value, **kwargs) # 這是也是新增cookie的方式,它最終還是調了set_cookie方法,在set_cookie基礎上又加了些操作 # set_signed_cookie裡又這樣一個引數salt,相當於加個暗號,讓你的cookie更加安全點 # 這個是不是和設定hash值差不多。 刪除cookie操作: delete_cookie 你只需要傳一個key值就行了 原始碼: def delete_cookie(self, key, path='/', domain=None): self.set_cookie(key, max_age=0, path=path, domain=domain, expires='Thu, 01-Jan-1970 00:00:00 GMT') 你看,它最終還是執行了set_cookie,只不過它把max_age設定為0 獲取到cookie值: 你請求的所攜帶的資料都在request物件中,所以這個cookie也不例外 方式一:cookie1 = request.COOKIES 方式二:cookie2 =request.META.get('HTTP_COOKIE') cookie1它的返回值是一個字典 {'sessionid': 'j17hk7jxd4excy1efmisirfv4bbjpcdu'} cookie2它就是一個字串了, request.COOKIES其本質就是通過cookie2的值進行字串操作,得到的字典 sessionid=j17hk7jxd4excy1efmisirfv4bbjpcdu # 用的話直接用request.COOKIES獲取cookie值就行 總結下cookie:1、它是儲存在瀏覽器中的鍵值對 2、檢視cookie,通過request.COOKIES,它是一個字典,取值就是字典取值了 3、set_cookie()和set_signed_cookie(),記住它是HttpResponse的方法
二、session
上面的講的cookie很好的解決了保持會話的效果,但是畢竟還是有限,它儲存在瀏覽器上對吧,那麼使用者就可以看到, 其他人也有機會切取到賬號密碼,所以對使用者來說存在一定的安全隱患的,所以必須要有新的保持會話的方式,所以 session這種方式,很好的解決了這個問題,將資料儲存在服務端上,外人不容易竊取到,況且還是加密儲存的 在django怎麼去設定session呢? request.session['name'] = 'zhuyu' # 這一行程式碼進行了下面幾個操作: 1、首先生成了一個隨機的字串,這個字串代表這這個瀏覽器的id 2、然後設定一個給這個瀏覽器設定一個cookie key為sessionid, value就是{'name':'zhuyu'}這個字典所通過加密得到的字串, 相當於執行HttpResponse.set_cookie('sessionid',字典加密後的字串) 3、然後儲存到資料庫中,這個表名為django_session 這樣一個瀏覽器就有了一個唯一的id,作為cookie的value值 那我在上面那行程式碼繼續執行一行程式碼 request.session['age'] = '21' 那django會進行怎麼的操作呢?是繼續執行下面那三個操作? 分析下:1、這是不是同一個瀏覽器發過去的資料,那麼這個隨機字串上面是不是已經生成了 2、基於1的想法,所以這個cookie是不是沒有發生變化,現在主要是考慮這個字典加密後的字串了 3、你覺得是生成一個新的加密字串覆蓋直接舊的?還是{'name':'zhuyu','age':'21'}生成 一個隨機字串再覆蓋掉之前的? 4、如果是基於3的想法一,生成一個字典加密的字串覆蓋掉之前的?那麼你的session永遠就是一個值? 你覺得這樣好嗎?後面我們可以要通過這個加密後的字串,反解密得到字典,再從資料庫中,拿到 該使用者的資訊,再返回到前臺頁面,那如果你的判斷調節就一個name,就一個age,是根本不能確定 是哪個使用者的 5、那應該就是組成一個大的字典,然後對字典進行加密操作,再儲存到資料庫中。 額額,上面這個這是我yy的,你如果知道的話,可以再下面留言,不過應該每人看的,還是讓我一個人在這裡yy吧,哈哈 request.session 這是一個物件,不是字典,他重寫了__getitem__,__setitem__這兩個方法 你可以把他當作一個字典去使用,get取值都行 {'name':'zhuyu','age':'21'} request.session 相當於就是個字典,那麼字典的一些方法,你可以使用 取值的話:request.session['name'] request.session.get('name') 設定session資料: request.session['sex'] = '男' request.session.setdefault('name','朱宇') # 意思是假如有name這個key,那就不賦值,沒有的話新增{'name':'朱宇'} 刪除其中的一個key值:del request.session['sex'] 你可以去試試pop行不行 返回值是列表: request.session.keys() request.session.values() request.session.items() 迭代器,每次返回一個數據: request.session.iteritems() request.session.iterkeys() request.session.itervalues() cookie_value = request.COOKIES.get('sessionid') request.session.exists(cookie_value) # 判斷sessionid對應的值,在不在django_session表的session_key中, # 假如瀏覽器的cookie中沒有sessionid,所以cookie_value為None, # 判斷就為false。 # 兩種刪除session的方式 方式一: request.session.delete() #這是刪除整個session,刪除的是那條記錄 #但是瀏覽器的cookie是不會刪掉的 那你下次瀏覽再帶這個cookie請求, request.session.exists(cookie_value)的值就為false了,因為資料庫中查詢不到 方式二: request.session.flush() # 刪除資料庫中的session,也刪除了瀏覽器的cookie # 你想想它是怎麼實現的? # 不就是執行request.session.delete(),再執行delete_cookie,就是這樣吧
三、在django的setting中配置session
1. 資料庫Session SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(預設) 2. 快取Session SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎 SESSION_CACHE_ALIAS = 'default' # 使用的快取別名(預設記憶體快取,也可以是memcache),此處別名依賴快取的設定 3. 檔案Session SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎 SESSION_FILE_PATH = None # 快取檔案路徑,如果為None,則使用tempfile模組獲取一個臨時地址tempfile.gettempdir() 4. 快取+資料庫 SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎 5. 加密Cookie Session SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎 其他公用設定項: 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,預設修改之後才儲存(預設)
四、基於FBV和CBV加上session裝飾器
之前寫過了,我就貼上了 基於FBV: def login_auth(func): def inner(request, *args, **kwargs): url = request.get_full_path() cook = request.COOKIES.get('sessionid') if request.session.exists(cook): return func(request, *args, **kwargs) else: return redirect('/login/?next_url=%s' % url) return inner # 假如你沒有登陸的話,訪問訂單頁面肯定是訪問不了,所以讓你先去登陸,登陸成功自動跳轉到訂單頁面 def login(request): print(request.session.set_expiry) if request.method == 'GET': return render(request, 'login.html') if request.method == 'POST': import json dic = json.loads(str(request.body, encoding='utf-8')) name = dic.get('name') pwd = dic.get('pwd') user = models.User.objects.filter(name=name, pwd=pwd) if user: request.session['name'] = name request.session['pwd'] = pwd path = request.GET.get('next_url') if path: url = path else: url = '/index/' new_dic = {'status': '100', 'info': url} else: new_dic = {'status': '200', 'info': '使用者名稱或密碼錯誤'} return JsonResponse(new_dic) @login_auth def order(request): return render(request, 'order.html') 基於CBV: class Buy_cart(views.View): def get(self, request): return HttpResponse('get') def post(self, request): return HttpResponse('post') @method_decorator(login_auth) def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) # 裝飾器在上面
## 今天就到這裡!!
## 提醒下,你要練習cookie,session的話,記得清理下瀏覽器的cookie,好了,沒事了