zoukankan      html  css  js  c++  java
  • 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表中比对相应的键值是否匹配,若匹配上,则自动登录。

  • 相关阅读:
    css中单位的使用
    css中max-width和min-width的应用
    css-样式初始化
    html中map标签和area标签的应用
    html中常见的小问题(1)
    防止图片被盗用
    关于thinkphp的__construct和_initialize
    禁用cookie后如何使用session还有session_id的使用
    is_null(self::$_instance) && self::$_instance = new self();
    echo、print、print_r、printf、sprintf、var_dump的区别
  • 原文地址:https://www.cnblogs.com/caoyu080202201/p/13054331.html
Copyright © 2011-2022 走看看