为什么会有cookie和session?

    浏览器向服务器发送http请求,建立session(会话),服务器返回完成,session结束,浏览器与服务断开

    再次发送http请求,重新建立会话,这就会出现用户信息丢失,服务器不能对请求的信息进行区分。

    A登陆帐户,服务器验证后,结束连接,A登陆的信息两边都没有记录,A再点其它连接,服务器就不知道是谁点的。。。

 

cookie和session是什么?

    为了跟踪用户和服务器之间的连接状态,先出现了cookie(存在客户端),后来发现不太安全,又出现了session(存在)

    Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。

 

一、cookie

    ※cookie信息以键值对的形式记录在客户端

    ※可以被修改

    ※浏览器提交请求自动附加cookie信息

    ※最大支持4096字节

    ※不可以跨域共享,比如京东不会识别到已登陆淘宝的用户信息

 

    1、设置cookie

        普通设置:set_cookie

        格式:set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False)

        注意:set_cookie是HttpResponse方法,所以只能用于redirect和HttpResponse,render没有此方法


         带加密的:set_signed_cookie,使用salt字符串进行签名认证,不仅检测cookie值,还检测salt生成的签名字符串

set_signed_cookie(key, value='', salt,max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False)

        选项功能:

参数作用name该Cookie的名称。Cookie一旦创建,名称便不可更改value该Cookie的值。如果值为Unicode字符,需要为字符编码。如果值为二进制数据,则需要使用BASE64编码maxAge该Cookie失效的时间,单位秒。如果为正数,则该Cookie在maxAge秒之后失效。如果为负数,该Cookie为临时Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。如果为0,表示删除该Cookie。默认为–1,常用max_age = 60*60*24(一天)expires

1、可以为秒,expires

2、可以为datetime时间格式

3、datime格式的字符串--源码里直接使用self.cookie[value]['expires']=str来设置,

      但是,并不生效,待探讨

需要注意的是服务器和客户端时间不同步问题

secure该Cookie是否仅被使用安全协议传输。安全协议。安全协议有HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false。当使用https式,必须要secure设置为Y=True。path该Cookie的使用路径。如果设置为“/sessionWeb/”,则只有contextPath为“/sessionWeb”的程序可以访问该Cookie。如果设置为“/”,则本域名下contextPath都可以访问该Cookie。注意最后一个字符必须为“/”domain可以访问该Cookie的域名。如果设置为“.google.com”,则所有以“google.com”结尾的域名都可以访问该Cookie。注意第一个字符必须为“.”httponly限制在浏览器控制台获取键值对,但无法对抓包工具进行限制。salt参数是字符串,加密cookie,客户端显示的是无序的cookie值。仅在set_signed_cookie下有效

# django views.pydef login(request):    user = request.GET.get('user',None)    # 获取值,如果没有,赋值None    pw = request.GET.get('pw',None)    if user=='david' and pw=='123456':        res = redirecte('index/')         res.set_cookie('username',user)            # 基于httpresponse类设置cookie                res.set_signed_cookie('pw','123456',salt="lakjsdfh")         # 使用salt生成签名,服务端使用get_signed_cookie获取,使用相同的salt进行签名认证            else:        res = redirecte('/djhw/')          # 用户名和密码不对则返回主页        return res

 

    2、读取cookie

            request.COOKIE.get():读取普通的cookie

            request.get_signed_cookie(),读取带签名的cookie,注意:要想设置默认值,写default=‘’

def index(request):    user = request.COOKIE.get('user',None)    # 获取cookie,如果没有,赋值None        pw = request.COOKIE.get('pw',None)            # 获取到的是:123456:加密的签名字符串        pw = request.get_signed_cookie('pw',None,salt)          # 使用salt,获取到的是:123456        if user == 'david' and pw == '123456':    # 判断获取的cookie是否和之前设置的一样        return render(request, 'hw/index.html')    # 如果一样,进入index页面    else:        return redirect('/djhw/')                  # 如果不一样,进入登陆面页

 

     3、删除cookie,delete_cookie()

res = redirect('/djhw/')res.delete_cookie('user_name')

 

    4、使用装饰器认证

#FBVdef auth(func):    def inner(request, *args, **kwargs)        username = request.COOLIES.get('user_name')    # 读取用户名        if username:                    return func(request, *args, **kwargs)      # 如果存在,返回传入的func函数        else:            return redirect('/djhw/')                  # 如果不存在,返回首页(登陆页)    return inner                                       # 返回结果        #CBVimport django.utils.decorators import method_decoratorform django import views方法一:使用类装饰器@method_decorator(auth,name='dispatch')class Blog(views.View):    def get(self,request):        username=request.COOKIES.get('user_name')        return render(request,'hw/index.html')        方法二:class Blog(views.View):    # 因为所有方法都是dispatch方法注册的,只装饰dispatch,所有方法都被装饰。    @auth    def dispatch(self,request,*args,**kwargs):        return super(Blog.self).dispatch(request,*args,**kwargs)    def get(self,request):        username=request.COOKIES.get('user_name')        return render(request,'hw/index.html')

 

二、session

 

    ※session信息以键值对的形式记录在服务端,存储位置可以在数据库、内存、文件

    ※服务端给用户所回一个随机字符串,客户端在Cookies中存储这个随机串

    ※客户端下次提交包含随机字符串,通过随机字符串获取session


    1、设置Session键值

        session是基于request的方法

def login(request):    # 设置和读取session键值    request.session['key1']='value1'              # 增加key1,如果键存在,更新值    request.session.setdefault('key2', 'value2')  # 增加key2,如果存在,不设置value2    request.session.get('key3','value3')    # key3存在,获取;不存在,增加key3,值为'value'    request.session['key1']                 # 获取Key1的值,如果不存在报错        # 查询是否存在session ID    request.session.exists('session id')    # 可用于数据库+缓存方式,缓存没有找数据库        # 设置session生效时间    request.session.set_expiry(value)    # 设置生效时长,value单位秒        # 如果value是个整数,session会在多少些秒后失效        # 如果value是个datetime或timedelta,session就会在这个时间后失效        # 如果value是0,用户关闭浏览器session就会失效        # 如果value是None,session会依赖全局session失效策略            request.session.clear_expired()        # datetime日期,把生效日期小于当前日期的session删除                # 删除    del request.session['key1']    # 删除session键    request.session.clear()        # 删除所有session键,session ID保留     request.session.delete()       # 删除当前session ID,参数可以放session ID,用户logout时用        # 查看session    request.session.items()        # 把键值对以列表显示[(k1,v1),(k2,v2)]    request.session.keys()         # 显示所有keys,[k1,k2]    request.session.values()       # 显示所有values,[v1,v2]    # 查看当前请求的session_id    request.session.session_key    # 存储在cookies的加密session ID

    2、session的全局配置:

        在settings.py文件中可以对session进行全局配置

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

    3、session的存储位置

        在settings.py文件中配置引擎,可以轻松改变session的存储位置

SESSION_ENGINE = 'django.contrib.sessions.backends.db'                    # 数据库(默认)SESSION_ENGINE = 'django.contrib.sessions.backends.file'                  # 文件SESSION_ENGINE = 'django.contrib.sessions.backends.cache'                 # 缓存SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'             # 缓存数据库SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'        # 加密cookie

 

    4、session保存在缓存(内存、memcache、redis)

        settings.py配置:

SESSION_ENGINE = 'django.contrib.sessions.babckends.cache'    # 设置引擎(缓存)SESSION_ENGINE = 'django.contrib.sessions.babckends.cache_db'    # 设置引擎(缓存+数据库),缓存找不到,去数据库找SESSION_CACHE_ALIAS = 'default'            # 指定CACHES里面的配置项名# CACHES里面可以有多项,但只有一个生效CACHES = {        'default':{        # 保存在内存        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',        'LOCATION': 'unique-snowflake',    }    'memcache':{        # 保存在内存    'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',    'LOCATION': ['ip1:port','ip2:port',],    }        'redis':{          # 保存在redis,django需要pip3 install django_redis安装    'BACKEND': 'django_redis.cache.RedisCache',    'LOCATION': 'redis://密码@IP:PORT/1',    'OPTIONS': {'CLIENT_CLASS':'django_redis.client.DefaultClient'},    }    }

 

    5、存储到文件

        settings.py

SESSION_ENGINE = 'django.contrib.sessions.backends.file'SESSION_FILE_PATH = None             # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile# SESSION_FILE_PATH = os.path.join(BASE_DIR, 'cache')SESSION_CACHE_ALIAS = 'default'            # 指定CACHES里面的配置项名CACHES = {    'default': {        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',        'LOCATION': '/var/tmp/django_cache',    }}