赞
踩
会话,可以理解为客户端与服务器之间的一次会晤,在一次会晤中可能包含多次的请求和响应,直到这次会晤结束,这整个过程就是一次会话。
比如你访问浏览器,浏览器客户端向某一服务器发出第一个请求开始,会话就开始了,直到客户关闭了浏览器会话结束。
在一个会话中的多个请求中共享数据,就是会话跟踪技术,例如:
在上述会话中,当前用户信息在这次会话中是共享的,登录的人和转账以及还款的人一定是相同的,也就是再一次会话中我们要实现数据共享的能力,**但是我们知道http协议是无状态和无连接的,**这个时候就需要别的机制来实现,也就是cookie技术。
我们知道HTTP协议是无状态的。
所谓无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况。
也就是说浏览器的请求对服务器来说,每次都是新的。
状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留。会话中产生的数据又是我们需要保存的,也就是说要“保持状态”。因此Cookie就是在这样一个场景下诞生。
cookie是浏览器的技术,Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。
cookie的工作原理是:浏览器访问服务端,带着一个空的cookie,然后由服务器产生内容,浏览器收到相应后保存在本地;当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie的内容来判断请求者是“谁”。
使用chrome浏览器,F12打开开发者工具,查看cookie
Cookie是通过HTTP请求和响应头在客户端和服务器端传递的:
如果服务器端发送重复的Cookie那么会覆盖原有的Cookie。
例如客户端的第一个请求服务器端发送的Cookie是:Set-Cookie: a=A;第二请求服务器端发送的是:Set-Cookie: a=AA,那么客户端只留下一个Cookie,即:a=AA。
关于cookie理解:
一个浏览器客户端并一个服务端对应一组cookie,多账号会覆盖。
意思是说,如果你使用同一个浏览器,登录一个帐号访问一个网址,只有一组cookie,如果你登录另外一个帐号访问这个网址,那么也只能存在一组cookie,后面登录的cookie会把之前的cookie顶替掉。
Ctrl + Shift + del三个键来清除页面缓存和cookie,将来这个操作你会用的很多
request.COOKIES['key'] # 通过键获取cookies中的某个值
request.COOKIES.get('key') # 推荐
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
参数说明:
cookie设置需要通过HttpResponse响应对象调用set_cookie方法来给cookie添加数据。
response = HttpResponse(...) # 或者 response = render(request,...)
# 设置不加盐cookie内容
response.set_cookie(key,value)
# 设置加盐cookie内容
response.set_signed_cookie(key,value,salt="加盐值",max_age=None,...)
参数说明:
删除cookie是通过HttpResponse对象调用delete_cookie方法删除
def logout(request):
response = redirect("/login/") # 获取响应对象
response.delete_cookie("user") # 删除用户浏览器上之前设置的usercookie值
return repsonse
from cookie_lesson import views
urlpatterns = [
# url(r'^admin/', admin.site.urls),
url(r'^login/', views.login,name="login"),
url(r'^home/', views.home,name="home"),
url(r'^logout/', views.logout,name="logout"),
]
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>欢迎来到主页</h1> <a href="{% url 'logout' %}"> 注销 </a> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script></script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>登录界面</h1> <form action="{% url 'login' %}" method="post"> {% csrf_token %} 用户名:<input type="text" name="username"> 密码:<input type="password" name="password"> <input type="submit"> </form> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script></script> </body> </html>
def auth(func): """定义装饰器,来对每个操作验证是否登录""" def wrapper(request): if request.method == "GET": # 获取cookie中的数据,如果有而且与服务端发送的cookie数据一致,就通过验证,无需重新登录,直接访问 is_login = request.COOKIES.get('is_login') username = request.COOKIES.get('user') if is_login == 'True' and username == "alex": ret = func(request) return ret return redirect('login') # 如果发现cookie中没有,则跳转登录页面 return wrapper def login(request): """登录函数""" if request.method=="GET": return render(request,'login.html') else: username = request.POST.get("username") password = request.POST.get("password") if username == "alex" and password == "alex": # 验证账号密码 ret = render(request,'home.html') # 登录成功后,添加cookie数据返回客户端 ret.set_cookie("is_login",True) ret.set_cookie("user",username) return ret else: return redirect('login') @auth def home(request): """展示主页,登录状态能访问""" return render(request, "home.html") @auth def logout(request): """注销,登录状态能访问""" res = redirect('login') res.delete_cookie('is_login') res.delete_cookie('user') return res
Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取。
因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是Session。
由于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”,我们仍需要cookie来起到桥接作用。
我们可以给每个客户端的Cookie分配一个唯一的id,这样用户在访问时,通过Cookie,服务器就知道来的人是“谁”。然后我们再根据不同的Cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。
Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie以文本的形式保存在本地,自身安全性较差;
通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。
在Django框架中,DJango框架已将cookie和session的数据封装好,存储在自己的数据库中的Django_session表中。
django将session的数据封装在request请求体中,注意session_id是Django帮我们自动生成的随机字符串。
request.session['key']
request.session.get('key',None)
从cookie里面将sessionid的值取出来,将django-session表里面的对应sessionid的值的那条记录中的session-data字段的数据给你拿出来(并解密)
request.session['key'] = 123 # 给session添加键值对数据
request.session.setdefault('key',123) # 如果键存在,不设置,不存在设置键值对
django-session这个表,你不能通过orm来直接控制,因为你的models.py里面没有这个对应关系
这里只展示views.py文件的代码,其他与模板文件和url配置与前面cookie版相同。
思路:我们平时访问页面,必须先登录,正常登陆会跳转到home页面。但是有一种情况,有人会直接访问index页面,比如淘宝的购物车,没有登录时去结算,会跳转到登录页面。
如果没有登录直接访问index页面,我们让他直接跳转到登录页面,这个时候如果用户正常登陆成功,我们应该是直接跳转到他之间想要访问的index页面,对不对。
就好比你淘宝去登录成功了,就是直接跳到了结算页面,并不需要你再去点结算页面。
这样用户体验才会比较舒服。
views.py文件
Views.py
数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)
缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
加密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,默认修改之后才保存(默认)
CBV添加装饰器的方式:视图函数中已经学习过。
需要导入一个装饰器方法
from django.utils.decorators import method_decorator
一个完整的url路由分发,装饰器验证登录的通过CBV模式实现的登录验证项目
项目下总路由分发文件urls.py
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
# url(r'^admin/', admin.site.urls),
url(r'^CBV_decoration', include("CBV_decoration.urls")), # include路径分发到应用CBV_decoration下的urls
]
from django.conf.urls import url
from CBV_decoration.views import Logout,Login,Home,Index
urlpatterns = [
url(r'/login/', Login.as_view(),name="login"), # 登录页面url
url(r'/home/', Home.as_view(),name="home"), # home页面url
url(r'/index/', Index.as_view(),name="index"), # index页面url
url(r'/logout/', Logout.as_view(),name="logout"), # 注销url
]
from django.shortcuts import render,redirect,HttpResponse from django.views import View from django.utils.decorators import method_decorator from functools import wraps # Create your views here. def auth(func): """定义装饰器,来对每个操作验证是否登录""" def wrapper(request,*args,**kwargs): if request.method == "GET": next_url = request.get_full_path() if request.session.get('user'): # 如果拿到了用户,说明已经登录,直接允许访问想要访问的页面 ret = func(request,*args,**kwargs) return ret else: # 如果没有登录,存下想要访问的url,让他先去登录 return redirect('CBV_decoration/login/?next={}'.format(next_url)) # 如果发现cookie中没有取到用户,则跳转登录页面,并且将想要访问的路径封装在get请求的url中 return wrapper class Login(View): """登录函数""" def get(self,request): return render(request,'login.html') def post(self,request): username = request.POST.get("username") password = request.POST.get("password") if username == "alex" and password == "alex": # 验证账号密码 request.session['user'] = username # 1.生成随机字符串session_id:随机字符串 # 2.加密用户信息,保存到数据库,Django中保存在Django_session表中 # 3.将session_id:随机字符串放到cookie发送客户端 next_url = request.GET.get('next') # 获取未登录是访问页面的路径 if next_url: # 如果有直接跳转 return redirect(next_url) else: # 没有的话正常登录到home页面 return redirect('home') class Home(View): """展示主页,登录状态能访问""" @method_decorator(auth) def dispatch(self, request, *args, **kwargs): ret = super().dispatch(request, *args, **kwargs) return ret def get(self,request): return render(request, "home.html") class Index(View): @method_decorator(auth) def dispatch(self, request, *args, **kwargs): ret = super().dispatch(request, *args, **kwargs) return ret def get(self,request): return render(request, "index.html") class Logout(View): """注销,登录状态能访问""" @method_decorator(auth) def dispatch(self, request, *args, **kwargs): ret = super().dispatch(request, *args, **kwargs) return ret def get(self,request): request.session.flush() # 删除当前的会话数据并删除会话的Cookie # request.session.delete() # 仅仅删除当前会话的所有Session数据 return redirect('login')
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>登录界面</h1> <form action="" method="post"> <!--注意action路径不填,提交到当前路径--> {% csrf_token %} 用户名:<input type="text" name="username"> 密码:<input type="password" name="password"> <input type="submit"> </form> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script></script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>Home页面</h1> <a href="{% url 'index' %}">进入首页</a> <br> <a href="{% url 'logout' %}"> 注销 </a> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script></script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>index页面</h1> <br> <a href="{% url 'logout' %}"> 注销 </a> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script></script> </body> </html>
通过jQuery获取cookie的数据,添加或者删除cookie键值对。
使用之jQuery操作cookie需要引入jQuery.cookie.js插件,而jQuery.cookie.js基于jQuery;
jQuery.cookie.js下载路径:http://plugins.jquery.com/cookie/
<script src="{% static 'jquery/3.4.1/jquery.js' %}"></script> <!--导入jQuery-->
<script src="{% static 'jquery.cookie.js' %}"></script> <!--引用jquery操作cookie的插件-->
$.cookie('key','value')
这里没有指明 cookie有效时间,所创建的cookie有效期默认到用户关闭浏览器为止,所以被称为 “会话cookie(session cookie)”。
$.cookie('key', 'value', { expires: 7 });
这里指明了cookie有效时间,所创建的cookie被称为“持久 cookie (persistent cookie)”。注意单位是:天;
$.cookie('key', 'value', { expires: 7, path: '/' });
在默认情况下,只有设置 cookie的网页才能读取该 cookie。
如果想让一个页面读取另一个页面设置的cookie,必须设置cookie的路径。cookie的路径用于设置能够读取 cookie的顶级目录。
将这个路径设置为网站的根目录,可以让所有网页都能互相读取 cookie (一般不要这样设置,防止出现冲突)。
$.cookie('key');
$.cookie('the_cookie', null); //通过传递null作为cookie的值即可
$.cookie('key','value',{
expires:7,
path:'/',
domain:'jquery.com',
secure:true
})
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。