Django中Cookie和Session使用

  • A+
所属分类:Python教程 学编程

一、Cookie

1.1、Cookie的由来

因为HTTP协议是无状态的,那么每次客户端和服务端交互都会产生一些数据,会话中产生的数据又是我们需要保存的,也就是说要“保持状态”。因此Cookie就是在这样一个场景下诞生。

1.2、Cookie是什么

Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。

1.3、Cookie的原理

cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie的内容来判断这个是“谁”了。

1.4、Django中使用Cookie

from django.shortcuts import render,redirect
from app01 import models

from functools import wraps

#装饰器函数(判断请求中是否存在Cookie)
def check_login(func):          #定义装饰器函数,参数是被装饰的函数
    @wraps(func)         #装饰器修复用的装饰器
    def inner(request,*args,**kwargs):          #接收被装饰函数的参数
        ret = request.get_signed_cookie("is_login", default="0", salt="login")        #获取Cookie
        if ret == "1":         #如果Cookie的值正确,继续向下执行
            return func(request,*args,**kwargs)
        else:          #如果没有登陆,就返回到登陆页面
            next_url = request.path_info        #获取参数信息
            # print(request.get_full_path())          #获取当前请求的全路径(路径与参数全有)
            # print(request.path_info)      #只获取路径
            return redirect("/app01/login/?next={}".format(next_url))      #将用户之前请求的地址设置为登陆页面的参数
    return inner       #返回函数

def login(request):
    #如果时post请求就执行这里
    if request.method == "POST":
        #获取用户名和密码和next参数
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")
        next_url= request.GET.get("next")
        if user == "zmr" and pwd == "abc123":
            if next_url:          #如果用户名密码对且有参数时就跳转到参数的页面
                ret = redirect(next_url)
            else:                 #如果登陆页面没有参数就跳转到默认页面
                ret = redirect("/app01/home/")
            # 登陆成功后,无论有没有参数都设置Cookie,Cookie的值为1然后加盐。max_age=7 * 24 * 60 * 60:Cookie过期时间,单位是秒(一周)
            ret.set_signed_cookie("is_login","1",salt="login",max_age=7 * 24 * 60 * 60)
            return ret        #返回跳转的页面(已设置cookie)
    #如果时get请求就执行这里
    return render(request, "app01/login.html")

#home函数,在函数里有判断Cookie的方法
def home(request):
    ret = request.get_signed_cookie("is_login",default="0",salt="login")     #获取Cookie的值,如果没有值默认设置为0
    if ret == "1":          #如果Cookie的是1
        return render(request, "app01/home.html")          #就到登陆后的页面
    else:
        return redirect("/app01/login/")         #否则就继续回到登陆页面

#index函数,使用前面写的检查Cookie的装饰器函数判断是否有Cookie
@check_login
def index(request):
    return render(request, "app01/index.html")

#注销函数(清除Cookie)
def logout(request):
    #如何删除cookie
    ret = redirect("/app01/login/")
    ret.delete_cookie("is_login")
    return ret

1.5、Cookeie的常用方法说明:

1.设置Cookie

rep = HttpResponse("Is OK !!")
rep = render(request, "test.html")

rep.set_cookie(key,value)     #设置Cookie
rep.set_signped_cookie("is_login","1",salt="login",max_age=7 * 24 * 60 * 60)      #设置Cookie,Cookie的值为1然后加盐。max_age=7 * 24 * 60 * 60:Cookie过期时间,单位是秒(一周)

2.获取Cookie

request.COOKIES['key']     #获取Cookie
request.get_signed_cookie("is_login", default="0", salt='is_login')     #获取Cookie

3.删除Cookie

def logout(request):
    rep = redirect("/login/")
    rep.delete_cookie("is_login")  # 删除用户浏览器上之前设置的is_login的cookie值
    return rep

二、Session

2.1、Session的由来

Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是Session。
我们可以给每个客户端的Cookie分配一个唯一的id,这样用户在访问时,通过Cookie,服务器就知道来的人是“谁”。然后我们再根据不同的Cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。

总结而言:Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。

另外,上述所说的Cookie和Session其实是共通性的东西,不限于语言和框架。

2.2、Django中Session的使用

1.FBV使用装饰器

from django.shortcuts import render,redirect
from django import views
#csrf防止跨站脚本的选择(Django提供了装饰器,可以指定某个页面不验证csrf(csrf_exempt),也可以指定某个页面验证csrf(csrf_protect))
from django.views.decorators.csrf import csrf_exempt, csrf_protect

from functools import wraps

#定义检查Session是否存在的装饰器
def check_login(func):          #定义装饰器函数,参数是被装饰的函数
    @wraps(func)         #装饰器修复用的装饰器
    def inner(request,*args,**kwargs):          #接收被装饰函数的参数
        ret = request.session.get("is_login")       #获取Session
        """
        取Session的步骤分为三步:
            1.获取Cookie中的随机字符串
            2.根据随机字符串去数据库取 Session_data --> 解密 --> 反序列化成字典
            3.在字典里 根据 is_login取具体数据
        """
        if ret == "1":         #如果Cookie的值正确(证明已登陆),继续向下执行
            return func(request,*args,**kwargs)
        else:          #如果没有登陆,就返回到登陆页面
            next_url = request.path_info      #获取当前请求的路径
            # print(request.get_full_path())          #获取当前请求的全路径(路径与参数全有)
            # print(request.path_info)      #只获取路径
            return redirect("/app02/login/?next={}".format(next_url))        #登陆页面后面设置用户原访问的页面路径为参数
    return inner

#登陆函数
def login(request):
    #如果是post请求就执行这里
    if request.method == "POST":
        #获取用户名、密码和URL参数
        user = request.POST.get("user")
        pwd = request.POST.get("pwd")
        next_url= request.GET.get("next")         #获取登陆页面传过来的next参数
        if user == "zmr" and pwd == "abc123":
            if next_url:     #登陆成功后,判断有没有参数,如果有参数就跳到参数的地址
                ret = redirect(next_url)
            else:           #如果没有参数就跳到指定的地址
                ret = redirect("/app02/home/")
            request.session["is_login"] = "1"        #设置Session,键为:"is_login"。值为:"1"
            request.session["username"] = user        #设置Session,键为:"username"。值为:获取到的 user 变量
            request.session.set_expiry(7)        #设置Session过期时间,7秒后失效
            return ret     #加上session后返回用户要访问的页面
    #如果是GET请求就执行这里
    return render(request, "app02/login.html")

@check_login    #使用检查Session的装饰器
def home(request):      #home函数
    ret = request.session.get("username")      # 获取Session里的用户名字段
    return render(request,"app02/home.html",{"username":ret})       #将用户名字段用于网页中

@check_login
def index(request):      #index函数
    return render(request,"app02/index.html")

#注销函数
def logout(request):
    #清除Session数据和Cookie
    request.session.flush()
    # request.session.delete()       #delete()只删除Session数据,不会删除Cookie数据
    '''
    flush和delete的区别:
        flush:清除Session和Cookie数据
        delete:只删除Session数据,不会清除Cookie数据

    只删除Session不删除Cookie数据会有什么问题:
        删除Session时不清除Cookie数据时,下次浏览器请求时会带有无用的Cookie,服务端在获取到无用的Cookie时到数据库里查询对应值时获取不到数据(会耽误时间)。
    '''
    return redirect("/app02/login/")

2.CBV使用检查Session的装饰器

from django.shortcuts import render,redirect
from django import views
#django提供的工具,把函数装饰器转变为方法(类的方法)装饰器
from django.utils.decorators import method_decorator

'''
CBV加装饰器:
    1.需要导入模块:from django.utils.decorators import method_decorator  
    2.可以单独给get方法加装饰器,也可以单独给post方法加装饰器,也可以给类加装饰器
    3.如果事给get或者事post方法加装饰器只需要指定:@method_decorator(check_login) 
    4.如果是给类加装饰器的时候需要通过name属性指定给什么方法加装饰器,如果给get方法加装饰器就用:@method_decorator(check_login, name="get")
'''
@method_decorator(check_login, name="get")
class UserInfo(views.View):
    def get(self,request):
        return render(request,"app02/userinfo.html")

2.3、Session相关设置

在settings.py中最后添加Session相关配置

#Session配置
SESSION_COOKIE_NAME = "sessionid"       #设置session的名字(key)
SESSION_SAVE_EVERY_REQUEST = True        #每次请求页面(点击页面)都更新session的过期时间(可以设置session的超时时间为一个小时,如果超过一个小时没点击页面就退出登陆,登陆后五十分钟点击一下页面就会更新session过期时间,即还有一个小时的时间)

2.4、Session相关方法说明

# 获取Session
request.session['k1']
request.session.get('k1',None)

#设置Session
request.session['k1'] = 123
request.session.setdefault('k1',123) # 存在则不设置

#删除Session中数据
del request.session['k1']

# 将所有Session失效日期小于当前日期的数据删除
request.session.clear_expired()

# 检查会话session的key在数据库中是否存在
request.session.exists("session_key")

# 删除当前会话的所有Session数据
request.session.delete()
  
# 删除当前的会话数据并删除会话的Cookie。
request.session.flush() 
    这用于确保前面的会话数据不可以再次被用户的浏览器访问
    例如,django.contrib.auth.logout() 函数中就会调用它。

# 设置会话Session和Cookie的超时时间
request.session.set_expiry(value)
    * 如果value是个整数,session会在些秒数后失效。
    * 如果value是个datatime或timedelta,session就会在这个时间后失效。
    * 如果value是0,用户关闭浏览器session就会失效。
    * 如果value是None,session会依赖全局session失效策略。

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: