1. 程式人生 > >django-cookie和session

django-cookie和session

一、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,好了,沒事了