zoukankan      html  css  js  c++  java
  • Django中的会话技术(Cookie,Session,Token)

    一、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 hashlib
    import random
    import time

    m = 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的所有优点,自己维护略微麻烦,支持更多的终端

  • 相关阅读:
    绝对路径和相对路径
    基本的文件操作
    Python2和3字符编码区别
    java开发两年了,连个java代理模式都摸不透,你怎么跳槽涨薪?
    【建议收藏】阿里P7总结的Spring注解笔记,把组件注册讲的明明白白
    面试官:你说你精通SpringBoot,你给我说一下类的自动装配吧
    面试BAT问的最多的27道MyBatis 面试题(含答案和思维导图总结)
    Springboot 框架整理,建议做开发的都看看,整理的比较详细!
    直面秋招!非科班生背水一战,最终拿下阿里等大厂offer!
    写的太细了!Spring MVC拦截器的应用,建议收藏再看!
  • 原文地址:https://www.cnblogs.com/huiyichanmian/p/12168685.html
Copyright © 2011-2022 走看看