Django中的会话技术(Cookie,Session,Token)

水痕 2020-01-08

一、Cookie

客户端技术,将数据信息存储到浏览器中,存储的结构是字典结构,即key-value.

Cookie是服务端创建,但保存于客户端,客户端每次发送请求时都会将Cookie信息发送到服务器(因为Cookie是请求头信息的一部分)

Cookie不支持中文,不能跨浏览器,不能跨域名

1、设置cookie

HttpResponse.set_cookie()

response.set_signed_cookie("Cookie名称","Cookie值",salt="盐")

属性:key

   value

   max-age  有效时长,单位为秒,指定为0,表示关闭浏览器失效(默认)指定为有效数值100表示100秒后自动失效,设置为None永不过期

   expires  支持一个datetime或timedelta,可以指定一个具体的日期,expires=timedelta(days=10)表示十天后过期

   max-age和xepires两个指定一个

# 普通设置,以明文的方式显示
def setcookie(request):
    response = HttpResponse(‘设置COOKIE成功‘)
    response.set_cookie(‘name‘,‘egon‘)
    return response
#加盐设置,以加密的形式显示
def do_login(request):

    uname = request.POST.get(‘uname‘)

    response = HttpResponseRedirect(reverse(‘app:mine‘))

    # response.set_cookie(‘uname‘, uname, max_age=60)
    response.set_signed_cookie(‘content‘, uname, "Rock")

    return response

2、获取

HttpRequest.COOKIES.get(key) 

request.get_signed_cookie("cookie名称",salt="盐")

def getcookie(request):
    return HttpResponse(request.COOKIES.get(‘name‘))
def mine(request):

    # uname = request.COOKIES.get("content")

    try:

        uname = request.get_signed_cookie("content", salt="Rock")

        if uname:
            # return HttpResponse(uname)

            return render(request, ‘mine.html‘, context={"uname": uname})
    except Exception as e:
        print("获取失败")

    return redirect(reverse(‘app:login‘))

3、删除

response.delete_cookie(key)

def logout(request):

    response = redirect(reverse("app:login"))

    response.delete_cookie("content")

    return response

二、Session

Session是用来表示一个用户与服务端的一次“会话”。使用客户端发送的sessionid(存在与Cookie中)与服务端的sessionid匹配,找到客户端请求所属的“会话”,经常用于登录验证。

Session一般保存在内存中,在Django中,Session默认使用数据库保存,若想变更Session的保存方式,需要添加SESSION_ENGINE配置信息,可以将session保存到redis中。

1、存储数据

 HttpRequest.session[key] = value,数据进行了base64编码

2、读取数据

request.session.session_key    获取session_id

HttpRequest.session.get(key)  

3、删除session

del request.session["key"]

request.session.flush()   同时清除cookie和session

request.session.clear()   清除所有session

def login(request):
    if request.method == "GET":
        return render(request, ‘two_login.html‘)
    elif request.method == "POST":
        username = request.POST.get("username")
        request.session["username"] = username
        return HttpResponse("登录成功")


def mine(request):
    username = request.session.get("username")
    print(request.session.session_key)
    return render(request, ‘two_mine.html‘, context=locals())


def logout(request):
    response = redirect(reverse(‘myapp:mine‘))
    # del request.session[‘username‘]
    # response.delete_cookie(‘sessionid‘)
    # session cookie一起干掉
    request.session.flush()
    return response

4、session重要配置

①、SESSION_EXPIRE_AT_BROWSER_CLOSE = True 

当浏览器关闭时,清除本地Cookie

②、 SESSION_COOKIE_AGE = 60 

设置session保存的秒数

5、扩展:将session保存到redis

 ①安装django-redis-sessions库

pip install django-redis-sessions

②在settings.py中配置

SESSION_ENGINE = ‘redis_sessions.session‘
SESSION_REDIS = {
    ‘host‘:‘127.0.0.1‘,
    ‘port‘:6379,
    ‘db‘:0,
    ‘password‘:‘Redis密码‘,
    ‘prefix‘:"key前缀",
    ‘socket_timeout‘:5    
}

 三、Token

Token是为了弥补服务端会话技术的缺点(占用服务器资源)而产生的,Token验证的思想是“以时间换空间”.

当第一次验证成功(用户名和密码正确),服务端对用户数据进行签名生成一个token,并将该token发送到客户端,当客户端发送请求时,会携带该token到服务器端,服务端对该token进行解密验证,当验证成功,则说明用户验证通过,否则验证失败.

1、基本算法

 ①MD5摘要算法

用来验证数据完整性 ,单向不可逆,防爆破性高,统一输出,默认输出128位的二进制,32位的16进制使用hexdigest()

import hashlib

md5 = hashlib.md5()
md5.update(‘xxx‘.encode())
crypto_str = md5.hexdigest()

②应用

基本时间+随机数生成MD5的32位字符串

import hashlibimport randomimport timem = hashlib.md5()m.update(str(time.time()+ random.random()).encode())a = m.hexdigest()

2、使用方式

①使用在移动端或客户端开发中,通常以Json形式传输,需要移动端自己存储Token,需要获取Token关联数据的时候,主动传递Token

def login(request):
    if request.method == "GET":
        return render(request, ‘two_login.html‘)
    elif request.method == "POST":
        username = request.POST.get("username")
        m = hashlib.md5()
        m.update(str(time.time()+ random.random()).encode())
        token = m.hexdigest()
        data = {
            ‘status‘: 200,
            ‘username‘: username,
            ‘token‘: token   # 设置token
        }
        return JsonResponse(data)
def mine(request):  # 客户端访问时候需要带上token  # http://127.0.0.1:8000/myapp/mine/?token=e912be747de3c51f11e9e9bea72b49bf    token = request.GET.get(‘token‘)    if token:        return JsonResponse({            ‘status‘: ‘OK‘        })

②在web开发中,Token和session类似,携带在cookie中。

def login(request):
    if request.method == ‘GET‘:
        return render(request, ‘login.html‘)
    else:
        name = request.POST.get(‘name‘)
        pwd = request.POST.get(‘pwd‘)
        users = User.objects.filter(name=name,pwd=pwd)
        if users:
            user = users.first()
            token = str(time.time())
            user.token = token
            user.save()
            response = HttpResponse(‘<h3 style="color:green">登录成功</h3>‘)
            response.set_cookie(‘token‘,token)       # 将token也保存于响应对象,发送给客户端
            return response

        else:
            return HttpResponse(‘用户名或密码错误‘)


def mine(request):
    token = request.COOKIES.get("token")
    if token:
        user = User.Objects.get(token=token)
        return HttpResponse(‘登录成功‘)

四、三者对比

 Cookie使用更简洁,服务器压力更小,数据不是很安全

Session服务器要维护Session,相对安全

Token拥有Session的所有优点,自己维护略微麻烦,支持更多的终端

相关推荐