一、网站发展史
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表中比对相应的键值是否匹配,若匹配上,则自动登录。