1. Cookie是什么
保存在浏览器端的键值对
2.为什么要有Cookie?
因为HTTP请求是无状态的
3.Cookie的原理?
服务端可以在返回响应的时候 做手脚
在浏览器上写入键值对(Cookie)
浏览器发送请求的时候会自动携带该网站保存在我浏览器的键值对(Cookie)
4.Django 从请求携带的Cookie中取值:
request.COOKIES['key'] request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
参数:
- key, 键
- value='', 值
- max_age=None, 超时时间
- expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
- path='/', Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问
- domain=None, Cookie生效的域名
- secure=False, https传输
- httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
5.Django中设置Cookie:(针对的是响应对象)
rep = HttpResponse(...) render(request, "xxx.html) redirect()
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key, value, salt="加密盐", max_age=7)
cookie版本的登录
from django.shortcuts import render, redirect # Create your views here. from functools import wraps def check_login(func): @wraps(func) # 装饰器修复技术 def inner(request, *args, **kwargs): ret = request.get_signed_cookie("is_login", default="0", salt="s10nb") if ret == "1": # 已经登陆过的 继续执行 return func(request, *args, **kwargs) # 没有登录过的 跳转到登录页面 else: # 获取当前访问的URL next_url = request.path_info print(next_url) return redirect("/login/?next={}".format(next_url)) return inner def login(request): print(request.get_full_path()) # 获取当前请求的路径和参数 print(request.path_info) # 取当前请求的路径 print("-" * 120) if request.method == "POST": user = request.POST.get("user") pwd = request.POST.get("pwd") # 从URL里面取到 next 参数 next_url = request.GET.get("next") if user == "alex" and pwd == "dsb": # 登陆成功 # 告诉浏览器保存一个键值对 if next_url: rep = redirect(next_url) # 得到一个响应对象 else: rep = redirect("/home/") # 得到一个响应对象 # rep.set_cookie("is_login", "1") # 设置加盐的cookie rep.set_signed_cookie("is_login", "1", salt="s10nb", max_age=10) # 单位是秒 return rep return render(request, "login.html") def home(request): # 从请求的cookie中找 有没有 xiaohei # ret = request.COOKIES.get("is_login", 0) # 取加盐过的 ret = request.get_signed_cookie("is_login", default="0", salt="s10nb") print(ret, type(ret)) if ret == "1": # 表示已经登陆过 return render(request, "home.html") else: return redirect("/login/") @check_login def index(request): return render(request, "index.html") # 注销函数 def logout(request): # 如何删除Cookie rep = redirect("/login/") rep.delete_cookie("is_login") return rep
6.Django中删除Cookie:(注销)
rep.delete_cookie(key)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1.Session是什么
Session保存在服务端的键值对 (值为自定义格式的字典)
Session依赖于Cookie
举个例子:
dsadasdsadsafsjkndf: {"is_login": 1, "name": "xiaohei", "age":18}
dsaasdaknfgreryywdf: {"is_login": 1, "name": "xiaobai", "age":20}
wqrqrteknfgzddasqfg: {"is_login": 0, "name": "xiaohui", "age":48}
给浏览器写入Cookie:
sessionid:wqrqrteknfgzddasqfg
1. 从用户发来的请求的Cookie中 根据 sessionid 取值, 取到 wqrqrteknfgzddasqfg
2. 根据特殊字符串找到对应的 Session 数据 --> {"is_login": 0, "name": "xiaohui", "age":48}
3. request.session.get("is_login") --> 从Session取值
Session流程解析:
总结cookie h和 session的区别:
a.cookie是保存在浏览器端的键值对,而session是保存在服务端的键值对,但是依赖cookie(也可以不依赖,可以放在url,或请求头但是cookie比较方便)
b.以登录为例,cookie为通过登录成功后,设置明文的键值对,并将键值对发送给客户端存储,明文信息可能存在安全泄漏,不安全
session则是生成随机字符串,发送给用户,并写道浏览器的cookie中,同时服务器自己也会保存一份
c.在验证登录时,cookie;根据浏览器发送请求是附带的cookie的键值进行判断。如果存在,则验证通过;
session 在请求用户的cookie中获取随机字符串,根据随机字符串在session中获取其对应的值进行验证
2.Django中设置Session:
request.session["is_login"] = 1
request.session.set_expiry(7) # 设置超时时间 (Cookie和Session数据的)
3.在settings.py中设置,每次请求都刷新Session超时时间
SESSION_SAVE_EVERY_REQUEST = True
4.Django中删除Session:
request.session.flush() 清除Cookie和Session数据
request.session.clear_expired() 将所有Session失效日期小于当前日期的数据删除
总结:Django中Session相关方法
# 获取、设置、删除Session中数据 request.session['k1'] request.session.get('k1',None) request.session['k1'] = 123 request.session.setdefault('k1',123) # 存在则不设置 del request.session['k1'] # 所有 键、值、键值对 request.session.keys() request.session.values() request.session.items() request.session.iterkeys() request.session.itervalues() request.session.iteritems() # 会话session的key request.session.session_key # 将所有Session失效日期小于当前日期的数据删除 request.session.clear_expired() # 检查会话session的key在数据库中是否存在 request.session.exists("session_key") # 删除当前会话的所有Session数据 request.session.delete() # 删除当前的会话数据并删除会话的Cookie。 request.session.flush() 这用于确保前面的会话数据不可以再次被用户的浏览器访问 例如,django.contrib.auth.logout() 函数中就会调用它。 # 设置会话Session和Cookie的超时时间 request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。
Session版本的登录
from django.shortcuts import render, redirect from django import views # Create your views here. from functools import wraps # Django提供的工具,把函数装饰器转变成方法装饰器 from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt, csrf_protect def check_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: # 获取当前访问的URL next_url = request.path_info print(next_url) return redirect("/app02/login/?next={}".format(next_url)) return inner @csrf_exempt def login(request): if request.method == "POST": user = request.POST.get("user") pwd = request.POST.get("pwd") # 从URL里面取到 next 参数 next_url = request.GET.get("next") if user == "alex" and pwd == "dsb": # 登陆成功 # 告诉浏览器保存一个键值对 if next_url: rep = redirect(next_url) # 得到一个响应对象 else: rep = redirect("/app02/home/") # 得到一个响应对象 # 设置session request.session["is_login"] = "1" request.session["name"] = user request.session.set_expiry(7) # 7秒钟之后失效 return rep return render(request, "app02/login.html") @check_login def home(request): user = request.session.get("name") return render(request, "app02/home.html", {"user": user}) @check_login def index(request): return render(request, "app02/index.html") # 注销函数 def logout(request): # 只删除session数据 # request.session.delete() # 如何删除session数据和cookie request.session.flush() return redirect("/app02/login/") # @method_decorator(check_login, name="get") class UserInfo(views.View): @method_decorator(check_login) def get(self, request): return render(request, "app02/userinfo.html")