DAY84-Django框架(十四) cookie and session

一、cookie

1.cookie

​ cookie 是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。

2.原理

​ cookie由服务器生成,发送给浏览器,浏览器把cookie以key:value形式保存到浏览器客户端上,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。

3.基本使用

#设置cookie,模拟服务器往浏览器发送cookie
def set_cookie(request):
    obj = HttpResponse('set_cookie')
    obj.set_cookie('name','xcq')
    obj.set_cookie('name','lqz')#对同一个key的cookie设置value,会覆盖
    return obj

#由于之前的默认设置,是在同一域名中,所以request可以拿到本地域名中的所有cookie
def get_cookie(request):
    print(request.COOKIES)#以字典形式接受
    print(request.COOKIES['name'])
    obj = HttpResponse('get_cookie')
    return obj

4.参数

#设置cookie
set_cookie(
    key, 			#键
    value='', 		#值
    max_age=None, 	#超时时间,以秒为单位,默认None,表示这个cookie会持续到浏览器关闭为止
    expires=None, 	#超时时间,与max_age一样,传一个datatime对象
    path='/',		#Cookie生效的路径,默认为‘/’,表示根路径可以被任何URL的页面访问
    domain=None, 	#Cookie生效的域名,默认为None,表示cookie只能由设置它的站点读取
    secure=False, 	#默认是false,设置成True浏览器将通过HTTPS来回传cookie
    httponly=False  #默认是false,设置成True就无法被JavaScript获取
):


5.加盐cookie

加盐是为了提高cookie的安全性,因为cookie是明文传递的

def set_cookie(request):
    obj = HttpResponse('set_cookie')
    obj.set_signed_cookie('name','xcq',salt='123')
    #密钥为123
    #加盐之后,会在xcq之后生成一串随机字符
    return obj


def get_cookie(request):
    # print(request.get_signed_cookie('name'))#不写密钥会报错
    print(request.get_signed_cookie('name',salt='123'))
    #想要获得原先的cookie值,要加上密钥
    obj = HttpResponse('get_cookie')
    return obj

6.删除cookie

def del_cookie(request):
    obj = HttpResponse('del_cookie')
    obj.delete_cookie('name')#只能删除指定key的cookie,无法全部删除
    return obj

7.在浏览器中查看

​ 浏览器中按F12,点network---cookies就能看到

8.简单实例

要求:

​ 1.做一个简单的登录

​ 2.做一个装饰器:点击别的页面,强制进入登录页面,登陆成功后跳转回之前的页面

def login_auth(func):
    def inner(request, *args, **kwargs):
        #拿到被装饰的页面路径
        url = request.get_full_path()
        if request.COOKIES.get('is_login'):
            res = func(request, *args, **kwargs)
            return res
        else:
            #把被装饰的页面路径通过get传递给登陆页面
            return redirect('/login/?next=%s' % url)

    return inner


def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')
    if request.method == 'POST':
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        if name == 'xcq' and pwd == '123':
            #登陆页面通过GET拿到之前的路径
            url = request.GET.get('next')
            if url:
                #登陆成功且是跳转的登陆,就跳转到之前的页面
                obj = redirect(url)
            else:
                obj=HttpResponse('主页')
            obj.set_cookie('is_login', 'True')
            obj.set_cookie('username', name)
            return obj
        return render(request, 'login.html')


@login_auth
def shopping(request):
    return HttpResponse('购物界面')


@login_auth
def order(request):
    return HttpResponse('订单界面')

二、session

1.session

​ session 从字面上讲,就是会话。这是为了解决cookie不安全而出现的

2.原理

​ 服务器为了知道当前发请求给自己的是谁,服务器就要给每个客户端分配不同的“身份标识”,然后客户端每次向服务器发请求的时候,都带上这个“身份标识”,服务器就知道这个请求来自于谁了。至于客户端怎么保存这个“身份标识”,可以有很多种方式,对于浏览器客户端,大家都默认采用 cookie 的方式。

​ 服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁。这种用户信息存储方式相对cookie来说更安全,可是session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。

3.基本使用

#设置session

def set_session(request):
    request.session['name']='xcq'
    # request.session['name']='lqz' #对同一个key设置value,会覆盖
    request.session['age']=18
    # request.session.setdefault('age',18)#如果已存在age字段,则不设置
    #设置session,其内部发生了三件事
    #   1.根据其浏览器客户端,生成了唯一的随机字符串sessionid
    
    #   2.去Django的内部数据库django_session存储
    #           session_key(随机字符串)       值(字典形式)                超时时间()
    #               sessionid            {'name':'xcq','age':18}       默认当前时间过两周
    
    #   3.设置了一个cookie:set_cookie('sessionid',随机字符串),浏览器只有通过sessionid来服务器找到对应的数据

    request.session.set_expiry(0)
    #如果value是个整数,session会在些秒数后失效。
    #如果value是个datatime或timedelta,session就会在这个时间后失效。
    #如果value是0, 用户关闭浏览器session就会失效。
    #如果value是None, session会依赖全局session失效策略。

    return HttpResponse('set_session')



#获取session

def get_session(request):
    # 获得session数据时:
    #	1.在cookie中获得sessionid对应的随机字符串
    #	2.去django_session中根据唯一sessionid获取对应数据
    
    # 拿到key对应的value,没有则报错
    print(request.session['name'])

    # 拿到value,没有不会报错
    print(request.session.get('age'))

    # 拿到所有的key
    print(request.session.keys())

    # 拿到所有的value
    print(request.session.values())

    # 拿到字典形式
    print(request.session.items())

    # 拿到sessionid
    print(request.session.session_key)
    return HttpResponse('get_session')



#删除session

def del_session(request):
    #删除对应的数据
    del request.session['name']
    #删除数据库的session
    request.session.delete()
    #删除数据库和cookie的session
    request.session.flush()
    # 将所有Session失效日期小于当前日期的数据删除
    request.session.clear_expired()
    print(request.session.items())
    return HttpResponse('del_session')

4.setting中的session设置

1. 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)

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

3. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
SESSION_FILE_PATH = None                                    # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() 

4. 缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎

其他公用设置项:
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写一个CBV的登陆装饰器

#重写父类的装饰器
class Login_user(View):
    #dispatch会对类里的所有方法有效
    def dispatch(self, request, *args, **kwargs):
        url = request.get_full_path()
        if request.session.get('is_login'):
            res = super().dispatch(request, *args, **kwargs)
            return res
        else:
            return redirect('/login/?next=%s' % url)


class Login(View):
    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        if name == 'xcq' and pwd == '123':
            url = request.GET.get('next')
            if url:
                obj = redirect(url)
            else:
                obj = HttpResponse('主页')
            request.session['is_login'] = True
            return obj
        return render(request, 'login.html')


class Shopping(Login_user):
    def get(self, request):
        return HttpResponse('购物界面')


class Order(Login_user):
    def get(self, request):
        return HttpResponse('订单界面')

方法二

from django.utils.decorators import method_decorator
def login_auth(func):
    def inner(request, *args, **kwargs):
        url = request.get_full_path()
        if request.COOKIES.get('is_login'):
            res = func(request, *args, **kwargs)
            return res
        else:
            return redirect('/login/?next=%s' % url)

    return inner


class Login(View):
    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        name = request.POST.get('name')
        pwd = request.POST.get('pwd')
        if name == 'xcq' and pwd == '123':
            url = request.GET.get('next')
            if url:
                obj = redirect(url)
            else:
                obj = HttpResponse('主页')
            request.session['is_login'] = True
            return obj
        return render(request, 'login.html')

#@method_decorator(指定装饰器,name=制定方法),如果没有写name=,那也会对所有方法有效
@method_decorator(login_auth,name='get')
class Shopping(View):
    def get(self, request):
        return HttpResponse('购物界面')

@method_decorator(login_auth,name='get')
class Order(View):
    #也可以写在方法上,只会装饰这个方法
    @method_decorator(login_auth)
    def get(self, request):
        return HttpResponse('订单界面')

三、cookie与session的区别

cookie 和session 的区别:

  1. cookie数据存放在客户的浏览器上,session数据放在服务器上。
  2. cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。
  3. session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能考虑到减轻服务器性能方面,应当使用COOKIE。
  4. 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

打个比方,浏览器客户端是我本人,而服务器就是银行。

​ 那么cookie就像是我手里存折,存折上面会记录你每一次的存取钱的记录,而cookie就是记录在浏览器上,我不用去问银行,就知道所有的记录;

​ 但session就像是银行卡,我本人手里只有银行卡和唯一的识别卡号,而所有关于我的数据记录都在银行里面,我只能通过卡号去银行(服务器)查询我的卡号所对应的所有的操作记录。

原文地址:https://www.cnblogs.com/xvchengqi/p/10003248.html