zoukankan      html  css  js  c++  java
  • django cookie&session


    cookie是什么

    由于http协议是无状态的,即服务器不知道用户的上一步操作是干了什么。这严重阻碍了交互式WEB应用程序的实现。cookie是http的一个额外的手段,用来保存用户的一部分信息到用户端,即cookie使保存在用户端的,由用户的浏览器来维护,通常被分为两种类型:内存cookie、硬盘cookie。cookie被夹带在http请求中,一般大小限制在4KB左右

    服务器在响应中添加设置过cookie后,支持cookie的浏览器都会做出反应,来使用某种方式来保存这个cookie,当用户下次再次发出请求的时候,浏览器判断当前cookie是否失效(expirse)、匹配路径(path)、匹配域名(domain)等操作后,将这段cookie加入到请求头中发送到服务器端。服务端对其进行处理

    在django中使用cookie

    • 实现保存用户登录状态
    # views.py
    def login(request):
        if request.method == "GET":
            return render(request, 'login.html')
        elif request.method == "POST":
            u = request.POST.get("username", None)
            p = request.POST.get("password", None)
            dic = user_info.get(u)
            print(dic)
            if not dic:
                return render(request, 'login.html')
            elif dic.get('pwd') == p:
               # 密码正确后设定cookie
                response = redirect('/index/')
                response.set_cookie("username", u)
                return response
            else:
                return render(request, 'login.html')
        else:
            return render(request, 'login.html')
    
    #index
    def index(request):
        ck = request.COOKIES.get("username")  # 早cookie中获取当前登录的用户
        if not ck:
             return redirect('/login/')
        return render(request, 'index.html', {'current_user': ck})
    

    当用户名和密码验证成功后,在返回的redirect中设定cookie。通过这种简单的例子即可以实现保存用户的登录状态,当用户下一次访问index的时候就不在需要登录

    • cookie的一些其他设定:

    1.request.COOKIES 用户发来数据中带来的COOKIE,为一个字典,可以使用get来获取
    2.response.set_cookie("字典的key",'字典的值') 后面不加参数的时候,只能设置一个当浏览器关闭就失效的cookie
    3.response.set_cookie("username",'value',max_age=10) 多少秒后过期的cookie
    4.通过datetime来设定过期

    current_date = datetime.datetime.utcnow()
    current_date = current_date+ datetime.timedelta(seconds=10)   # 当前时间加上10s后
    response.set_cookie("username", u, expires=current_date)  # 设定到哪个时间点后失效,如果时间设置与当前时间相同,那么就是清除这个cookie
    

    5.设定cookie作用的路径

    response.set_cookie("username", u,path='/index/')  # 设置这个cookie只在当前url生效,例如设定一个cookie为当前页面显示多少条数据,别的页面就不会被干扰
    

    6.domain='' 为当前设置cookie的域名
    7.secure = False 为https传输设置cookie
    8.httponly = True 设置cookie只做为http传输,不可以被js获取到。在js中使用document.cookie获取可以所有cookie,或者使用JQuery也可以操作cookie

    9.带salt的cookie

    # 设定加盐
    COOKIE_SALT = "随机字符串"
    response.set_signed_cookie('username', u, salt=COOKIE_SALT)
    
    # 加盐获取
    ck = request.get_singed_cookie("username",salt=COOKIE_SALT)
    

    session

    session是什么

    参考:晋哥哥的私房钱

    session一般被译为会话,从不同的角度上来看到会话,是有不同的意义的:

    1. 从用户的角度来看,他打开一个网站,并进行了一系列的浏览、登录、购物等操作,这就可以被称为一个会话
    2. 从底层来细细分析呢,由于http的无状态性,用户登录我们需要保存他的登录状态,当前购物车中的所有商品都需要保存下来,所以我们需要一个特定的数据结构来保存这些数据。这个东西就被称为session

    所以session是一种基于http协议的用于增强http的一种数据存储结构或方案,session存储在服务端。服务端创建session的一般步骤分为:生成一个全局唯一标识sessionid,在对应的数据中开辟存储空间,然后将session的全局唯一标识符发送到客户端。 服务端为每一个session维护一份会话信息数据,而客户端和服务端依靠一个全局唯一的标识来访问会话信息数据。

    那么客户端和服务端怎么发送这个标识符呢?一般实现有两种方式:

    • cookie,服务端通过设定cookie的方式,将sessionid发送到客户端
    • url重写,在返回用户请求的页面之前,将页面内所有的URL后面全部以get的方式加上session标识符,用户在下次操作上,都会加上这个标识符,从而实现了会话保持,这也是当用户禁用cookie的做有效的办法

    cookie与session的对比

    1. 应用场景
    • Cookie的典型应用场景是记住密码、记住我操作,用户的账户信息通过cookie的形式保存在客户端,当用户再次请求匹配的URL的时候,账户信息会被传送到服务端,交由相应的程序完成自动登录等功能。当然也可以保存一些客户端信息,比如页面布局以及搜索历史等等。
    • Session的典型应用场景是用户登录某网站之后,将其登录信息放入session,在以后的每次请求中查询相应的登录信息以确保该用户合法。当然还是有购物车等等经典场景;
    1. 安全性
    • cookie将信息保存在客户端,如果不进行加密的话,无疑会暴露一些隐私信息,安全性很差,一般情况下敏感信息是经过加密后存储在cookie中,但很容易就会被窃取。
    • session只会将信息存储在服务端,如果存储在文件或数据库中,也有被窃取的可能,只是可能性比cookie小了太多。这里涉及到的是硬件安全,但是总体来说session的安全性要高于cookie;
    1. 性能
    • Cookie存储在客户端,消耗的是客户端的I/O和内存,而session存储在服务端,消耗的是服务端的资源。
    • session对服务器造成的压力比较集中,而cookie很好地分散了资源消耗,就这点来说,cookie是要优于session的;
    1. 时效性
    • Cookie可以通过设置有效期使其较长时间内存在于客户端,而
    • session一般只有比较短的有效期(用户主动销毁session或关闭浏览器后引发超时);
    1. 其他
      Cookie的处理在开发中没有session方便。而且cookie在客户端是有数量和大小的限制的,而session的大小却只以硬件为限制,能存储的数据无疑大了太多。

    django中使用session

    注:

    1. django默认使用django.contrib.sessions.models.Session模块,将session存储在数据库的django_session 表中,当然这些都是可以配置的

    2. 所以需要在使用database-backed sessions前进行一定的设定,在数据库当中生成存储session的表以及字段

    python manage.py makemigrations
    python manage.py migrate
    
    • 简单实现
    # views.py
    def login(request):
        if request.method == "GET":
            return render(request, "login.html")
    
        if request.method == "POST":
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
            rmb = request.POST.get('rmb',None)
            print(rmb)
            if user == 'root' and pwd == "123":
                # 直接设定值
                request.session['username'] = user
                request.session['is_login'] = True
                if rmb == "10":
                    request.session.set_expiry(10)  # 设置多少秒后过期
                # 生成的session默认存储在django的默认数据库中
                return redirect('/index/')
            else:
                return render(request, "login.html")
    
    def logout(request):
        # 注销
        if request.method == 'POST':
            print(request.session.get('username'))
            request.session.delete(request.session.session_key) # 从数据库中删除
            print(request.session.session_key)
            print(request.session.get('username'))
            return redirect('/login/')
    
    def index(request):
        if request.session.get('is_login'):
            return render(request, 'index.html')
        else:
            return HttpResponse("Fuck off")
    
    • 在这样的应用中访问会在数据库中生成以下数据

    session-table

    • 更多操作
    1. 获取session中的值
    request.session['k1']
    request.session.get('k1',None)
    2. 设定session中的值
    request.session['k1'] = 123
    request.session.setdefault('k1',123) # 存在则不设置
    3. 删除session对应的值
    del request.session['k1']
    4. 由于session的真是数据结构其实是个字典对象,所以拥有字典的一些方法:
    request.session.keys() # 所有的key
    request.session.values() # 所有的value
    request.session.items() # 键值对元组
    # 其他方法
    request.session.iterkeys() # key的可迭代对象
    request.session.itervalues() # value的可迭代对象
    request.session.iteritems()  # 键值对元组的可迭代对象
    5. 用户的全局唯一sessionid
    request.session.session_key
    6. 将所有Session失效日期小于当前日期的数据删除
    request.session.clear_expired()
    7. 判断是否存在
    request.session.exists("session_key")
    8. 删除这个sessionid,并也会删除其对应的数据
    request.session.delete("session_key")
    9. 过期设定
    request.session.set_expiry(value)
        * 如果value是个整数,session会在些秒数后失效。
        * 如果value是个datatime或timedelta,session就会在这个时间后失效
        * 如果value是0,用户关闭浏览器session就会失效。
        * 如果value是None,session会依赖全局session失效策略。(默认是两个周)
    
    • 配置相关

    1.引擎相关
    除了django自己支持的以下几种引擎以外,还可以使用redis作为session的存储,可以参考redis的设置方法 猛戳

    # 数据库存储
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'
    # 缓存存储
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
    # 文件存储
    SESSION_ENGINE = 'django.contrib.sessions.backends.file'
    SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
    # 缓存加数据库
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
    # 加密cookie Session
    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
    

    2.通用设定

    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,默认修改之后才保存
    
  • 相关阅读:
    东汉末年,他们把「服务雪崩」玩到了极致(干货)
    我是一个秒杀请求,正在逃离这颗星球...
    《SpringCloud实战项目》系列目录
    《Java并发必知必会》系列
    微前端大赏二-singlespa实践
    redis传输协议规范(翻译)-上(Redis Protocol specification)
    oracle 查询数据库锁及锁处理
    golang string 转 int && int 转 string
    Json刚明白,怎么又出来个Bson?
    Linux中的buffer和cache到底是什么?今天终于明白了
  • 原文地址:https://www.cnblogs.com/forsaken627/p/12521965.html
Copyright © 2011-2022 走看看