cookie与session

一、网站发展史

  1、无需甄别来访问的用户:早期的网站都没有保存用户记录的需求,任何用户何时何地访问网站是没有任何区别的,如现代一些网站,新闻,纯公告,等等。

  2、需要甄别不同的用户:后来有些网站需要甄别用户信息返回对应结果,如,淘宝,收费视频,等等。

二、cookie与session的由来与原理:以登录功能为例,如果不保存客户的登录状态,也就意味着每当客户离开前页面时,登录状态即消失,无论是再次访问同样页面,还是跳转同站其他页面时,都需要再次进行登录,可想而知,如此非常不人性化。

  1、优化方式一:

    当用户首次登录成功后,服务端就把用户的登录信息返回给客户端浏览器,使之在本地保存。

    后续访问同站任何页面时,由浏览器自动将本地的用户登录信息发给服务端校验,服务端返回校验结果,浏览器则展示为已登录的状态,给客户一种自动登录的体验。

    但是,这种方式存在较大的信息泄露隐患。

    这就是cookie的基本原理。

    所有的服务端保存于客户端浏览器的用户信息,不只限于登录信息,都可以称为cookie,表现形式为若干个kv键值对。

  2、优化方式二:

    当用户首次登录成功后,服务端则会产生一个随机字符串,然后将该字符串作为键,对应用户信息这个值,保存于服务端的数据库中,只把这个随机字符串交于客户端浏览器保存。

    后续访问同站任何页面时,由浏览器自动将本地的随机字符串发给服务端,服务端以该字符串为键查找校验用户信息,然后返回校验结果,浏览器则展示为已登录的状态,同样给客户一种自动登录的体验。

    该方式较方式一在信息安全上有了一定的提升,但也并非无懈可击。

    这就是session的基本原理。

    所有的服务端需要保存于客户端浏览器的用户信息,都可以转化为对应的随机字符串,不只限于登录信息,这些都称为session。

  3、小结:

    cookie:真正的用户信息保存在本地客户端浏览器。

    session:真正的用户信息保存在服务端数据库。

    session本质上还是基于cookie的原理工作的。

三、cookie的具体操作

  1、选择性保存:户端浏览器可以通过设置,来拒绝保存服务端返回的用户信息,如此任何通过该浏览器产生的用户信息都无法保存。

  2、相关操作语句:

    ①request.COOKIES.get(已有键):获取某个已存cookie的值。

    url_obj.set_cookie(自定义键/已有键, 自定义值, max_age = 整数, expires = 整数):

      ---添加/修改cookie。

      ---设置cookie保存时间,单位为秒。

      ---同是设置cookie保存时间,IE浏览器专用。

    url_obj.delete_cookie(已有键):删除指定cookie。

    url_obj.set_signed_cookie(自定义键/已有键, 自定义值, salt = 自定义盐):添加/修改带标记的cookie。

    request.get_signed_cookie(已有键, salt = 已有盐):获取某个已存带标记的cookie。

  3、实例:

    urls.py:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$', views.home, name='home'),
    url(r'^login/', views.login),
    url(r'^page_1/', views.page_1),
    url(r'^page_2/', views.page_2),
    url('^logoff/', views.logoff)
]

    views.py:

# 登录验证
def login(request):
    if request.method == 'POST':
        recv_username = request.POST.get('post_username').strip()
        recv_password = request.POST.get('post_password').strip()
        # 模拟数据库校验
        if recv_username == 'tom' and recv_password == '111':
            # 尝试获取跳转来此之前页面的路由
            tar_url = request.GET.get('tar_url')
            if tar_url:
                # 若存在这个路由,下一步跳转回原页面
                next_url_obj = redirect(tar_url)
            else:
                # 若不存在这个路由,则是直接登录的,下一步跳转主页
                next_url_obj = redirect('home')
            # 让客户端浏览器记录一个登录标志,键的名字和值都可以另外自定义
            next_url_obj.set_cookie('login_tag', recv_username)
            # 执行跳转
            return next_url_obj
        else:
            return HttpResponse('账号或密码错误')
    return render(request, 'login_page.html')


# 将登录验证功能作为装饰器
def add_login(func):
    def passer(request, *args, **kwargs):
        # 获取当前页面的url
        tar_url = request.get_full_path()
        # 若cookie里面有登录信息, 执行原视图函数
        if request.COOKIES.get('login_tag'):
            res = func(request, *args, **kwargs)
            return res
        # 否则跳转登录页面,同时传递当夜页面的url
        else:
            return redirect('/login/?tar_url={}'.format(tar_url))

    return passer


@add_login
def page_1(request):
    return render(request, 'page_1.html')


@add_login
def page_2(request):
    return render(request, 'page_2.html')


@add_login
def logoff(request):
    next_url_obj = HttpResponse('已注销')
    # 删除已存登录标志,实现注销
    next_url_obj.delete_cookie('login_tag')
    return next_url_obj


def home(request):
    return render(request, 'home_page.html')

    templates---home_page.html:

<body>
<h1>我是主页</h1>
<p><a href="login">去登录页面</a></p>
<p><a href="page_1">去1号页面</a></p>
<p><a href="page_2">去2号页面</a></p>
<p><a href="logoff">注销登录</a></p>
</body>

    templates---login_page.html:

<body>
<form action="" method="post" novalidate>
    <p><label for="">username:<input type="text" name="post_username"></label></p>
    <p><label for="">password:<input type="password" name="post_password"></label></p>
    <p><input type="submit" value="登录"></p>
</form>
</body>

四、session的具体操作

  1、session表:只要用django操作过一次数据库,就会在该数据库中自动创建很多表,其中有一张名为<django_session>的表,就是与session操作相关的表。

  2、相关操作语句:

    request.session[自定义键/已有键] = 自定义值 --- 添加/修改session中某个键值对。

    request.session.get(已有键) --- 获取session中某个已存的键的值。

    request.session.set_expiry(x) --- 设置session的过期时间。  

      x为0:随浏览器的关闭而失效。

      x为日期对象:过期时间点。     

      x为整数:代表过期时间为x秒。

      不设置此项:采用django默认的过期时间,14天。

      最后两种情况下,每次刷新session,如再次访问网站,过期时间也会随之重新计算。

    request.session.delete():删除session,只删除服务器的,不删除客户端浏览器的,用得少。

    request.session.flush():删除session,同时删除服务器和客户端浏览器的,常用。

  3、session其他相关:

    session的可存放位置:数据库,文件,缓存,等等。

    django_session表中的session,一个session中可以存放多个键值对,对同一个ip的同一个浏览器而言,永远只有一条有效,只有当上一条session过期时,才会出现新旧session并存的情况,此时为了清除无效数据节省数据库资源,可以人为通过代码清除过期的session,若不人为清除,也会在一段时间后被系统自动清理。

  4、以登录功能为例,简析session机制:

    登录成功后,可以创建一组新的键值对。

    然后在服务端django_session中会生成随机字符串(若已有该浏览器和ip对应的随机字符串,则沿用已有的),该字符串就是一个session。

    将这组键值对存于这个session中,返回session对应的字符串给客户端浏览器保存于本地。

    后续在该ip下用同一浏览器访问页面时,客户端浏览器会自动从本地调出保存的字符串去服务端的django_session表中比对相应的键值是否匹配,若匹配上,则自动登录。

原文地址:https://www.cnblogs.com/caoyu080202201/p/13054331.html