目录html
首先咱们须要了解一下什么是会话?咱们能够把会话看成成客户端与服务器之间的一次会晤,在一次会晤期间会有屡次请求和响应。例如你打电话给10086客服,那么此时你就是客户端,10086客服就是服务端,那么一次会晤就是大家在打电话期间的聊天过程。直到某一方挂了电话,此时表示会话结束。在大家的通话过程当中,你会向10086发送屡次请求,那么这些请求都会保存在一个会话中。python
在JavaWeb中,客户端向服务器发出第一个请求开始,会话就开始了,直到客户端关闭了浏览器会话结束。web
在一次会话中的多个请求须要共享数据,这就是会话跟踪技术。例如在一个会话中的请求以下:数据库
在以上此次会话中,当前用户的信息必须是要在此次会话中共享的,由于登录的是zhangsan,那么转帐和还款确定是用zhangsan用户转帐和还款,这就说明咱们必须在一个会话过程当中有共享数据的能力。django
HTTP协议是一种不保存状态,即无状态协议。HTTP协议自身不对请求和响应之间的通讯状态进行保存。也就是说在HTTP这个级别,协议对于发送过的请求或响应都不作持久化处理。
浏览器
使用HTTP协议,每当有新的请求发送时,就会有对应的新响应产生。协议自己并不保留以前一切的请求或响应报文的信息。这是为了更快的处理大量事务,确保协议的可伸缩性,而特地把HTTP协议设计的如此简单的。安全
但是,随着web的不断发展,因无状态而致使业务处理变得棘手的状况增多了。好比我们刚刚说的请求银行、登录、转帐、还款的问题。虽然HTTP协议是无状态协议,但为了实现指望的保持状态功能,因而引入了cookie技术。有了cookie再用HTTP协议通讯,就能够管理状态了。服务器
cookie翻译成中文是小甜点、小饼干的意思。在HTTP中它表示从服务器送给客户端的小甜点。其实cookie是key-value结构,和python的字典比较相似。随着服务器端的响应发送给客户端浏览器,而后客户端浏览器会把cookie保存起来,当下一次再访问服务器时就把cookie再发送给服务器。cookie
cookie是由服务器端建立,而后经过响应发送给客户端的一个键值对。客户端会保存cookie,并会标注cookie的来源。当客户端向服务器发出请求时会把全部这个服务器cookie的包含在请求中发送给服务器,这样服务器就能够识别客户端了。
session
让咱们用代码级别来看一下cookie长什么样子?
首先咱们须要新建立一个项目,而后设置路由规则:
urls.py
from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('login/', views.login), ]
views.py
from django.shortcuts import render,HttpResponse,redirect # Create your views here. def login(request): return render(request, 'login.html')
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Login页面</title> </head> <body> <form action="" method="post"> {% csrf_token %} 用户名 <input type="text" name="user"> 密码 <input type="text" name="pwd"> <input type="submit" value="submit"> </form> </body> </html>
而后在model.py中建立模型类
from django.db import models # Create your models here. class UserInfo(models.Model): user = models.CharField(max_length=32) pwd = models.CharField(max_length=32)
使用数据库迁移命令来生成数据库:
python3 manage.py makemigrations python3 manage.py migrate
最后在数据库中插入两条记录:
那么当咱们把整个项目运行起来后,当咱们输入用户名和密码若是正确以后,那么就在浏览器设置一个cookie而后响应给客户端,那么咱们须要在views.py中去进行判断了:
from django.shortcuts import render,HttpResponse,redirect from app01.models import UserInfo # Create your views here. def login(request): if request.method == 'POST': user = request.POST.get('user') pwd = request.POST.get('pwd') user = UserInfo.objects.filter(user=user, pwd=pwd).first() if user: response = HttpResponse('登录成功') response.set_cookie({'is_login': True}) return response return render(request, 'login.html')
此时我们在浏览器输入正确的用户和密码后,让咱们看下这次响应的内容:
此时的cookie已经放在响应体中了,当客户端向此服务器发送请求的时候,就会携带上这个cookie,当咱们刷新此界面,就能够看到了携带了此cookie:
那么咱们能够去模仿某网站了,若是你登录过,那么就进入index界面,若是没有那就强制跳转到登录界面。首先咱们要写一条路由规则:
urls.py
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('login/', views.login), path('index/', views.index), ]
views.py
from django.shortcuts import render,HttpResponse,redirect from app01.models import UserInfo # Create your views here. def login(request): if request.method == 'POST': user = request.POST.get('user') pwd = request.POST.get('pwd') user = UserInfo.objects.filter(user=user, pwd=pwd).first() if user: response = HttpResponse('登录成功') response.set_cookie('is_login', True) response.set_cookie('username', user.user) return response return render(request, 'login.html') def index(request): is_login = request.COOKIES.get('is_login') if is_login: username = request.COOKIES.get('username') return render(request, 'index.html', locals()) else: return redirect('/login/')
此时views.py中就是当用户再login界面登录后,系统会设置cookie将当前状态和登录用户名记录下来而后响应给客户端,而后当用户访问index界面中,首先就去判断用户是否登录,若是没有登录那么就重定向到login页面中,若是登录则跳出欢迎界面。
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Index</title> </head> <body> <h3>这是主界面</h3> <p>hello,{{ username }}</p> </body> </html>
那么下图就是浏览器访问index所携带的cookie:
class HttpResponseBase: def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False, samesite=None): """ Set a cookie. ``expires`` can be: - a string in the correct format, - a naive ``datetime.datetime`` object in UTC, - an aware ``datetime.datetime`` object in any time zone. If it is a ``datetime.datetime`` object then calculate ``max_age``. """ self.cookies[key] = value if expires is not None: if isinstance(expires, datetime.datetime): if timezone.is_aware(expires): expires = timezone.make_naive(expires, timezone.utc) delta = expires - expires.utcnow() # Add one second so the date matches exactly (a fraction of # time gets lost between converting to a timedelta and # then the date string). delta = delta + datetime.timedelta(seconds=1) # Just set max_age - the max_age logic will set expires. expires = None max_age = max(0, delta.days * 86400 + delta.seconds) else: self.cookies[key]['expires'] = expires else: self.cookies[key]['expires'] = '' if max_age is not None: self.cookies[key]['max-age'] = max_age # IE requires expires, so set it if hasn't been already. if not expires: self.cookies[key]['expires'] = http_date(time.time() + max_age) if path is not None: self.cookies[key]['path'] = path if domain is not None: self.cookies[key]['domain'] = domain if secure: self.cookies[key]['secure'] = True if httponly: self.cookies[key]['httponly'] = True if samesite: if samesite.lower() not in ('lax', 'strict'): raise ValueError('samesite must be "lax" or "strict".') self.cookies[key]['samesite'] = samesite
那么经过这段源码咱们能够看出来除了响应体设置cookie由key-value参数,还有一些其余的参数,例如超长时间max_age,cookie生效的路径path等。
有时候咱们但愿用户在登录某网站一段时间后cookie就过时,那么咱们就能够设置超长时间
views.py
from django.shortcuts import render,HttpResponse,redirect from app01.models import UserInfo # Create your views here. def login(request): if request.method == 'POST': user = request.POST.get('user') pwd = request.POST.get('pwd') user = UserInfo.objects.filter(user=user, pwd=pwd).first() if user: response = HttpResponse('登录成功') response.set_cookie('is_login', True, max_age=20) # 超长时间 response.set_cookie('username', user.user) return response return render(request, 'login.html') def index(request): is_login = request.COOKIES.get('is_login') if is_login: username = request.COOKIES.get('username') return render(request, 'index.html', locals()) else: return redirect('/login/')
那么当咱们用户登录login页面后,再去访问index界面,等待15秒钟后会自动重定向到login界面。
expires默认None ,cookie失效的实际日期/时间。
这个和max_age不同的是这个要写时间的字符串。
views.py
import datetime date = datetime.datetime.strftime(year=2018, month=11, day=21, hour=3, minute=51, second=0) # 东八区 response.set_cookie('is_login', True, expires=date)
那么这样写的意思就是在2018年11月22日 上午11时51分00秒这个cookie失效。能够自行去测试的,这个我就不演示了。
cookie生效的路径,浏览器只会把cookie回传给带有该路径的页面,这样能够避免将cookie传给站点中的其余应用。也就是说:若是个人index页面须要cookie,那么我就只须要在path后面设置为此页面就能够了,其他的并不须要。
views.py
def login(request): if request.method == 'POST': user = request.POST.get('user') pwd = request.POST.get('pwd') user = UserInfo.objects.filter(user=user, pwd=pwd).first() if user: response = HttpResponse('登录成功') import datetime # date = datetime.datetime.strftime(year=2018, month=11, day=21, hour=3, minute=51, second=0) # 东八区 response.set_cookie('is_login', True, path='/login/') response.set_cookie('username', user.user) return response return render(request, 'login.html')
此时我们设置的路径就是login页面,为了验证效果,当咱们输入正确的信息后,当再次输入地址进入index界面中,由于cookie生效路径没有index,那么就会自动跳转到login页面了。
本次暂不演示。
response.delete_cookie("cookie_key",path="/",domain=name)
session是一个服务器端技术,利用这个技术,服务器在运行时能够为每个用户的浏览器建立一个独享的session对象,因为session为用户浏览器独享,因此用户在访问服务器web资源时,能够把各自的数据存放在各自的session表中,当用户再去访问服务器中的其余web资源时,其余Web资源再从用户各自的session中取出数据为用户服务。
session基于cookie实现的会话跟踪,cookie存放在客户端一旦丢失的话就会对用户的数据构成威胁。
咱们来看一下cookie的保存:
当咱们输入正确的帐号和密码后,由服务器端响应体设置的cookie就会传给客户端,那么客户端再次请求的时候就会拿这个cookie去请求,由于是明文的、存放在浏览器的将变的十分不安全。
那么让咱们来看一下session怎么作的?
首先设置两条路由规则views.py:
path('login_session', views.login_session), path('index_session', views.index_session),
同时设置视图函数views.py
# session def login_session(request): return render(request, 'login.html') def index_session(request): return render(request, 'index.html')
那么session是怎么和cookie不一样的呢?
views.py
def login_session(request): if request.method == 'POST': user = request.POST.get('user') pwd = request.POST.get('pwd') user = UserInfo.objects.filter(user=user, pwd=pwd).first() if user: request.session['is_login'] = True request.session['username'] = user.user return HttpResponse('登录成功') return render(request, 'login.html')
当咱们去浏览器访问下能够看到此时的sessionid:
在这里不一样的是session和cookie建立的步骤不一样:
那么到最后返回到客户端的就是一个sessionid,当客户端浏览器再请求服务器时,服务器就会根据这个sessionid在djano_session表中查找这么一条记录,咱们在建立数据库的时候django_session表已经自动建立好了。
那么此时我们设置一个视图函数,看看session的数据是怎么找到的:
views.py
def index_session(request): print(request.session.get('is_login')) is_login = request.session.get('is_login') if not is_login: return redirect('/login_session/') username = request.session.get('username') return render(request, 'index.html', locals())
session去找数据也是三个步骤,首先要确认是否是第一次访问,若是是那么就添加词条记录,若是不是那就更新操做:
删除session值:del request.session['username']
views.py
def index_session(request): print(request.session.get('is_login')) del request.session['username'] is_login = request.session.get('is_login') if not is_login: return redirect('/login_session/') # username = request.session.get('username') return render(request, 'index.html', locals())
那么此时我们访问login_session后再访问index_session的时候,此时的username被咱们删掉了,而后此时刷新界面是这样的:
flush():删除当前的会话数据并删除会话的Cookie。
logout.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Index</title> </head> <body> <h3>这是主界面</h3> <p>hello,{{ username }}</p> <a href="/logout/">注销</a> </body> </html>
views.py
def logout(request): request.session.flush() return redirect('/login_session/')
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Index</title> </head> <body> <h3>这是主界面</h3> <p>hello,{{ username }}</p> <a href="/logout/">注销</a> </body> </html>
此时点击注销标签,此时就会删除当前会话的cookie。
django中默认支持session的,而且默认是将Session数据存储在数据库中,即:django_session 表中。
配置settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认) 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,默认修改以后才保存(默认)
views.py
def login_session(request): if request.method == 'POST': user = request.POST.get('user') pwd = request.POST.get('pwd') user = UserInfo.objects.filter(user=user, pwd=pwd).first() if user: request.session['is_login'] = True request.session['username'] = user.user import datetime now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') request.session['time'] = now return HttpResponse('登录成功') return render(request, 'login.html')
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Index</title> </head> <body> <h3>这是主界面</h3> {# <p>hello,{{ username }}</p>#} <p>上次登录时间:{{ time }}</p> <a href="/logout/">注销</a> </body> </html>
基于cookie也是相似的作法。