8

Cookie和Session

一、cookie和session的介绍

cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生。

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

cookie虽然在一定程度上解决了“保持状态”的需求,但是由于cookie本身最大支持4096字节,以及cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是session。

cookie和session的区别

Cookie是保存在用户浏览器端的键值对,Session是保存在服务器端的键值对;Cookie做用户验证的时,敏感信息不适合放在Cookie中,别人可以分析存放在本地的Cookie并进行Cookie欺骗,考虑到安全应当使用Session;用户验证时两者要结合使用,Session可保存到文件,内存,数据库任意地方.

cookie存储到客户端
优点:数据存储在客户端。减轻服务端的压力,提高网站的性能
缺点:安全性不高,在客户端很容易被查看或破解用户会话信息
session存储到服务器
优点:安全性高
缺点:服务器压力大

Cookie的简单使用

1、获取Cookie
request.COOKIES.get("islogin",None)  #如果有就获取,没有就默认为none
request.COOKIES['key']
request.COOKIES.get('key')
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
    参数:
        default: 默认值
           salt: 加密盐
        max_age: 后台控制过期时间
2、设置cookie
rep = HttpResponse(...) 或 rep = render(request, ...) #return的对象

rep.set_cookie(key,value,...)
rep.set_cookie("haiyan","344",20)  #20代表过期时间
# 普通cookie是明文传输的,可以直接在客户端直接打开,所以需要加盐,解盐之后才能查看
rep.set_signed_cookie(key,value,salt='加密盐',...)
    参数:
        key,              键
        value='',         值
        max_age=None,     超时时间 单位秒
        expires=None,     超时时间(IE requires expires, so set it if hasn't been already.) 单位日期
        path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问 指定生效路径
        domain=None,      Cookie生效的域名
        secure=False,     https传输改为True
        httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖
复制代码
# max_age 10秒失效
result.set_cookie('username',u,max_age=10)
 
# expires 设置失效日期
import datetime
current_date = datetime.datetime.utcnow()
current_date = current_date + datetime.timedelta(seconds=5)
result.set_cookie('username',u,expires=current_date)
 
# 加密
obj = HttpResponse('s')
obj.set_signed_cookie('username',"kangbazi",salt="asdfasdf")
request.get_signed_cookie('username',salt="asdfasdf")

3、删除Cookie

obj.delete_cookie("cookie_key",path="/",domain=name)

session的简单使用

1、获取session
# 获取Session中数据
request.session['k1']
request.session.get('k1', None)
2、设置session
# 生成Session中数据
request.session['k1'] = 123
request.session.setdefault('k1', 123)  # 不存在则设置
3、删除session
# 删除Session中某条数据
del request.session['k1']

# 删除当前用户的所有Session数据
request.session.delete("session_key")
request.session.clear()    
request.session.flush() # 删除当前的会话数据和会话cookie。经常用在用户退出后,删除会话。
# 登出时使用flush()方法是比较安全的一种做法,而且一次性将session中的所有内容全部清空,确保不留后患。但也有不好的地方,那就是如果你在session中夹带了一点‘私货’,会被一并删除,这一点一定要注意。
4、类似字典数据类型的内置方法
request.session.keys()
request.session.values()
request.session.items()
request.session.setdefault('k1', 123) 
request.session.clear() 
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()
5、其他方法
# 用户session的随机字符串
request.session.session_key
 
# 将所有Session失效日期小于当前日期的数据删除
request.session.clear_expired()
 
# 检查用户session的随机字符串是否 在数据库中
request.session.exists("session_key")

request.session.set_expiry(value)
        # 设置cookie的有效期。可以传递不同类型的参数值:
        • 如果值是一个整数,session将在对应的秒数后失效。例如request.session.set_expiry(300) 将在300秒后失效.
        • 如果值是一个datetime或者timedelta对象, 会话将在指定的日期失效
        • 如果为0,在用户关闭浏览器后失效
        • 如果为None,则将使用全局会话失效策略
        失效时间从上一次会话被修改的时刻开始计时。
request.session.get_expiry_age()
            # 返回多少秒后失效的秒数。对于没有自定义失效时间的会话,这等同于SESSION_COOKIE_AGE.
            # 这个方法接受2个可选的关键字参数
        • modification:会话的最后修改时间(datetime对象)。默认是当前时间。
        •expiry: 会话失效信息,可以是datetime对象,也可以是int或None

set_test_cookie()
            # 设置一个测试cookie,用于探测用户浏览器是否支持cookies。由于cookie的工作机制,你只有在下次用户请求的时候才可以测试。
        test_cookie_worked()
            # 返回True或者False,取决于用户的浏览器是否接受测试cookie。你必须在之前先调用set_test_cookie()方法。
        delete_test_cookie()
            # 删除测试cookie。

session的存储

Django提供了一个通用的Session框架,并且可以使用多种session数据的保存方式:

  • 保存在数据库内
  • 保存到缓存
  • 保存到文件内
  • 保存到cookie内

通常情况,没有特别需求的话,请使用保存在数据库内的方式,尽量不要保存到Cookie内。

1.数据库存储session

Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session表中

配置settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.db'  # 引擎(默认)

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,默认修改之后才保存(默认)
                                    #  设置Ture后,每次点击页面,时间更新

2.缓存存储session

配置settings.py

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
SESSION_CACHE_ALIAS = 'default'  # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置

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,默认修改之后才保存

可以设置为Memcache缓存

配置settings.py

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
SESSION_CACHE_ALIAS = 'db'  # 使用的缓存别名,此处别名依赖缓存的设置

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': [
            '172.19.26.240:11211',
            '172.19.26.242:11211',
        ]
    },
    'db': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': [
            '172.19.26.240:11211',
            '172.19.26.242:11211',
        ]
    }
}

3.使用redis缓存session

SESSION_ENGINE='redis_sessions.session'
SESSION_REDIS_HOST='localhost'
SESSION_REDIS_PORT=6379
SESSION_REDIS_DB=0
SESSION_REDIS_PASSWORD=''
SESSION_REDIS_PREFIX='session'

#通过redis-cli客户端可以查看:
127.0.0.1:6379> select 0
OK
127.0.0.1:6379[0]> keys *
1) "session:0bjyuegx0i5ivyuzpb8ezgo0b35u2z4v"

4.文件存储session

配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
    SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()  
                                                                # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
  
    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,默认修改之后才保存

5.缓存加数据库session

数据库用于做持久化,缓存用于提高效率,先去缓存中取数据,缓存没有再去数据库中取,然后在缓存中存一份

配置settings.py

SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'  # 引擎

6.加密cookie session

数据都存在于客户端
配置settings.py

SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'  # 引擎

示例:

from django.shortcuts import render,redirect

# Create your views here.
import datetime

def login(request):
    print("COOKIES",request.COOKIES)  #打印cookies 一个字典,里面多个键值对
    print("SESSION",request.session)  #session为服务器对应客户信息的键

    if request.method=="POST":
        name=request.POST.get("user")
        pwd=request.POST.get("pwd")
        if name=="yuan" and pwd=="123":

            # ret=redirect("/index/")
            # 给对象ret设置cookie 安全性较差  ,设定有效时间max_age,expires,
            # ret.set_cookie("username",{"11":"22"},max_age=10,expires=datetime.datetime.utcnow()+datetime.timedelta(days=3))
            # return ret

            # COOKIE SESSION一起使用
            # session 以字典存放在服务器端,发给客户端的是数据对应的键,
            request.session["is_login"]=True  # 在session中增加键值对
            request.session["user"]=name

            return redirect("/index/")

    return render(request,"login.html")


def index(request):
    if request.COOKIES.get("username",None):   # 取不到设置默认值为None
        name = request.COOKIES.get("username",None)
        return render(request, "index.html", locals())

    # session验证 存在数据库中,所以要先makemigrations生成数据库
    if request.session.get("is_login",None):
        name=request.session.get("user",None)
        return render(request,"index.html",locals())
    else:
        return redirect("/login/")
##session获取
request.session.get("user",None)
# 设置
request.session["user"]=name
# 删除
del request.session.get("user")

rayzz
145 声望13 粉丝

引用和评论

0 条评论