Cookie和session
摘要:
cookie和session的区别:
1.cookie:
cookie是保存在浏览器端的键值对,可以用来做用户认证
2.session:
将用户的会话信息保存在服务端,key值是随机产生的字符串,value值是session的内容
依赖于cookie将每个用户的随机字符串保存到用户浏览器上
Django中session默认保存在数据库中:django_session表
flask,session默认将加密的数据写在用户的cookie中
Cookie
在一个会话的多个请求中共享数据,就是会话跟踪技术
HTTP协议是无状态协议,每个请求都是独立的!无法记录前一次请求的状态。
但HTTP协议中可以使用Cookie来完成会话跟踪!
在Web开发中,使用session来完成会话跟踪,session底层依赖Cookie技术
Cookie的概念:
Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对
Cookie的原理:
1.客户端向服务端发送请求,第一次的值为空 cookie:{}
2.服务端接受请求后,设置cookie,request.set_cookie(key,value,),随着响应发给浏览器
3.客户端浏览器会把Cookie保存起来,当下一次再访问服务器时把Cookie再发送给服务器
当客户端向服务器发出请求时会把所有这个服务器Cookie包含在请求中发送给服务器,这样服务器就可以识别客户端了!
Cookie与HTTP头 :
Cookie是通过HTTP请求和响应头在客户端和服务器端传递的:
1.客户端请求:
请求头中携带Cookie:{key,value}
格式:Cookie: a=A; b=B; c=C。即多个Cookie用分号离开
2.服务端响应:
响应头中携带Set-Cookie:{key,value}
一个Cookie对象一个Set-Cookie:
Set-Cookie:a=A Set-Cookie: b=B Set-Cookie: c=C
如果服务器端发送重复的Cookie那么会覆盖原有的Cookie,例如客户端的第一个请求服务器端发送的Cookie是:Set-Cookie: a=A;第二请求服务器端发送的是:Set-Cookie: a=AA,
那么客户端只留下一个Cookie,即:a=AA。
1.设置Cookie
rep = HttpResponse(...) rep = render(request, ...) rep.set_cookie(key,value,...) rep.set_signed_cookie(key,value,salt='加密盐',...) 加密 return rep
2.获取cookie
request.COOKIES.get("is_login") request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
3.删除Cookie
def logout(request): # 如何删除Cookie rep = redirect("/login/") rep.delete_cookie("is_login") return rep
简单的cookie操作
def login(request): if request.method=="POST": name=request.POST.get("username") passwd=request.POST.get("password") if name=="jerd" and passwd=="123": ##使用cookie,让浏览器保存一个键值对 rep=redirect("/home/") # rep.set_cookie("is_login","1") #明文 ##使用密文## rep.set_signed_cookie("is_login","1",salt="jerd") return rep return render(request,"login.html") def home(request): ##进行判断,如果登录成功就能进入到家目录,没登录,就去登录 # ret=request.COOKIES.get("is_login") #传过来的是字符串 ret=request.get_signed_cookie("is_login",default='0',salt="jerd") if ret=="1": return render(request, "home.html") else: return render(request, "login.html")
使用装饰器
def is_login(func): def inner(request,*args,**kwargs): ret=request.get_signed_cookie("is_login",default='0',salt="jerd") if ret == "1": return func(request,*args,**kwargs) else: return render(request,"login.html") return inner @is_login def index(request): return render(request, "index.html")
Cookie版登陆校验
如果是从其他页面跳转到登录页面,在登录成功后,跳转到之前的页面 from functools import wraps def is_login(func): @wraps(func) # 装饰器修复技术 def inner(request,*args,**kwargs): ret=request.get_signed_cookie("is_login",default='0',salt="jerd") if ret == "1": return func(request,*args,**kwargs) else: now_url=request.path_info #获取当前访问的url return redirect("/login/?next={}".format(now_url)) return inner def login(request): print("-" * 120) print(request.get_full_path()) # 获取当前请求的路径和参数 print(request.path_info) # 取当前请求的路径 print("-" * 120) if request.method=="POST": name=request.POST.get("username") passwd=request.POST.get("password") next_url = request.GET.get("next") # 从URL里面取到 next 参数 print(next_url) if name=="jerd" and passwd=="123": ##使用cookie,让浏览器保存一个键值对 ##如果是从其他页面跳转到登录页面,在登录成功后,跳转到之前的页面 if next_url: rep = redirect(next_url) #直接进登录页面,登陆后,默认跳到home页面 else: rep=redirect("/home/") # rep.set_cookie("is_login","1") #明文 ##使用密文 一周有效## rep.set_signed_cookie("is_login", "1", salt="jerd",max_age=7*24*60*60) return rep return render(request,"login.html") def home(request): ##进行判断,如果登录成功就能进入到家目录,没登录,就去登录 # ret=request.COOKIES.get("is_login") #传过来的是字符串 ret=request.get_signed_cookie("is_login",default='0',salt="jerd") if ret=="1": return render(request, "home.html") else: return render(request, "login.html") @is_login def index(request): return render(request, "index.html") ##删除cookie## def logout(request): rep=redirect("/login/") rep.delete_cookie("is_login") return rep 在登录页面中,就不能再提交给login {#从其他页面跳到登录页面时,此时login后面带有参数,提交时就不能再提交给login#} {#<form action="/login/" method="post">#} <form action="{{ request.get_full_path }}" method="post">
Session
Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie本身保存在客户端,可能被拦截或窃取,自身安全性较差;
而Session保存在服务器,有较高的安全性。
所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息
session的特性:
Session是服务器端技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,
由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,
当用户再去访问该服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。
Session的类型
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
]
Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:
1.数据库(默认)
2.缓存
3.文件
4.缓存+数据库
5.加密cookie
1、数据库Session:Django默认将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,默认修改之后才保存(默认)
2.缓存session:将session放到缓存中
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存)
SESSION_COOKIE_NAME = "sessionid"
3.文件session:将session放到文件中
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址
SESSION_COOKIE_NAME = "sessionid"
4.缓存+数据库Session
数据库用于做持久化,缓存用于提高效率
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
5.加密cookie Session:将session加密后放到cookie中(flask就是这样的)
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
常用操作:
1.设置session: request.session["is_login"]="1" 2.获取session: request.session.get(""is_login") 3.只删除session数据 request.session.delete() 4.删除session数据和cookie request.session.flush() 5.设置会话Session和Cookie的超时时间 request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 cookie值消失 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。 6.在setting中添加 SESSION_SAVE_EVERY_REQUEST =True 每次请求都保存Session设置后,如果存在数据库中,需要迁移数据库
使用makemigrations和migrate后,数据库中会泽东生成一张session表,存放着k和data
Session版登陆验证
from functools import wraps def is_login(func): @wraps(func) # 装饰器修复技术 def inner(request,*args,**kwargs): ret=request.session.get("is_login") #获取时的流程## # 1. 获取cookie中的随机字符串 # 2. 根据随机字符串去数据库取 session_data --> 解密 --> 反序列化成字典 # 3. 在字典里面 根据 is_login 取具体的数据 if ret == "1": return func(request,*args,**kwargs) else: now_url=request.path_info #获取当前访问的url return redirect("/login/?next={}".format(now_url)) return inner def login(request): print("-" * 120) print(request.get_full_path()) # 获取当前请求的路径和参数 print(request.path_info) # 取当前请求的路径 print("-" * 120) if request.method=="POST": name=request.POST.get("username") passwd=request.POST.get("password") next_url = request.GET.get("next") # 从URL里面取到 next 参数 if name=="jerd" and passwd=="123": if next_url: rep = redirect(next_url) #直接进登录页面,登陆后,默认跳到home页面 else: rep=redirect("/home/") request.session["is_login"]="1" ##可以设置多个值,但都存在一个k只 k:{"is_login":"1","name":user} request.session.set_expiry(100) # 100秒钟之后失效 request.session["name"] = name return rep return render(request,"login.html") @is_login def home(request): user=request.session.get("name") #获取到用户名 return render(request, "home.html",{"username":user}) @is_login def index(request): return render(request, "index.html") ##删除## def logout(request): request.session.flush() return redirect("/login/")
cookie和session总结
1.COOKIE的由来:
因为HTTP请求时没有状态的,每一次请求都是独立的,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况。
2.cookie就是保存在浏览器上的键值对
服务器控制着响应,在响应里可以让浏览器在本地保存键值对,下次请求再发送的时候就会自动携带这个cookie值。浏览器关闭,cookie就失效
3.cooie的应用:1.七天免登陆 2.记录用户的浏览器习惯 3.简单的投票规则
4.服务端:
1. 生成字符串
2. 随着响应将字符串回复给浏览器
3. 从浏览器发送的请求中拿到字符串
好处:
服务端不用存,减轻了服务器压力
坏处:
信息不安全
session:保存在服务端的键值对,必须依赖于cookie
在服务器端存在的形式 sadsjhsjkcehhw:{"is_login":1,"user":"jerd"}
Django中session的执行存过程:
存session: request.session["is_login"]="1"
1.在服务端生成随机字符串
2.生成一个和上面随机字符串对应的大字典,用来保护疏忽数据
3.随机字符串当成cookie返回给浏览器
取session:ret=request.session.get("is_login")
1.从请求携带的cookie里面找到随机字符串
2.拿到的随机字符串去session中找对应的大字典
3.从大字典中根据key取值
session的优势:
1.比cookie能存的数据多
2.安全性好,数据存在服务端
坏处:
数据都保存在服务端,存储压力比较大