什么你还不会cookie、session的相关操作,大量案例帮你理解!小白必看! 以前的网站都是静态的,早期的论坛,新闻网页都是不需要登录的,但是随着发展,动态网站的诞生需要登录使用,我们知道HTTP协议的四大特性之一是无状态,就是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况;
状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留。会话中产生的数据又是我们需要保存的,也就是说要“保持状态”。因此Cookie就是在这样一个场景下诞生
Cookie的结构是key-value结构,类似于python中的字典,随着服务器端的响应发送给客户端浏览器。然后客户端浏览器会把Cookie保存起来,当下一次再访问服务器时把Cookie再发送给服务器。 Cookie是由服务器创建,然后通过响应发送给客户端的一个键值对。客户端会保存Cookie,并会标注出Cookie的来源(哪个服务器的Cookie)。当客户端向服务器发出请求时会把所有这个服务器Cookie包含在请求中发送给服务器,这样服务器就可以识别客户端了;
cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie的内容来判断这个是“谁”了;
上面的数据只是HTTP的Cookie规范,但在浏览器大战的今天,一些浏览器为了打败对手,为了展现自己的能力起见,可能对Cookie规范“扩展”了一些,例如每个Cookie的大小为8KB,最多可保存500个Cookie等!但也不会出现把你硬盘占满的可能!
注意,不同浏览器之间是不共享Cookie的。也就是说在你使用IE访问服务器时,服务器会把Cookie发给IE,然后由IE保存起来,当你在使用FireFox访问服务器时,不可能把IE保存的Cookie发送给服务器;
如果服务器端发送重复的Cookie那么会覆盖原有的Cookie,例如客户端的第一个请求服务器端发送的Cookie是:Set-Cookie: a=A;第二请求服务器端发送的是:Set-Cookie: a=AA,那么客户端只留下一个Cookie,即:a=AA;

rep = HttpResponse(...)# 普通设置rep.set_cookie(key,value)# 加盐设置rep.set_signed_cookie(key,value,salt='加密盐')# 设置过期时间,单位是秒rep.set_signed_cookie(key,value,salt='加密盐',expires=3600)# 获取cookierequest.COOKIES['key']request.COOKIES.get('key')# 获取加盐cookierequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)'''default: 默认值salt: 加密盐max_age: 后台控制过期时间'''def logout(request): rep = redirect("/login/") rep.delete_cookie("user") # 删除用户浏览器上之前设置的usercookie值 return rep# 设置cookiedef set_cookie(request): set_obj = HttpResponse('set cookie successfuly!') # set_obj.set_cookie('name', 'Hammer','nb',expires=3600) set_obj.set_signed_cookie('name', 'Hammer','nb') # set_obj.set_cookie('is_login', True) return set_obj# 获取cookiedef get_cookie(request): get_obj = HttpResponse('get cookie successfuly!') # name = request.COOKIES.get('name') name1 = request.get_signed_cookie('name',salt='nb') print(name1) return get_obj# 更新cookiedef update_cookie(request): upd_obj = HttpResponse('update cookie successfuly!') name = upd_obj.set_cookie('name','Hans') print(name) return upd_obj# 删除cookiedef delete_cookie(request): del_obj = HttpResponse('delete cookie successfuly!') del_obj.delete_cookie('is_login') return del_obj'''models.py'''class UserInfo(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=64)'''urls.py'''from django.contrib import adminfrom django.urls import pathfrom cookie import viewsurlpatterns = [ path('admin/', admin.site.urls), path('login/', views.login), path('index/', views.index), path('logout/', views.logout), path('order/', views.order)'''views.py'''def login(request): if request.method == "GET": return render(request, "login.html") username = request.POST.get("username") password = request.POST.get("pwd") user_obj = models.UserInfo.objects.filter(username=username, password=password).first() print(user_obj.username) if not user_obj: return redirect("/login/") else: rep = redirect("/index/") rep.set_cookie("is_login", True) return rep def index(request): print(request.COOKIES.get('is_login')) status = request.COOKIES.get('is_login') # 收到浏览器的再次请求,判断浏览器携带的cookie是不是登录成功的时候响应的 cookie if not status: return redirect('/login/') return render(request, "index.html")def logout(request): rep = redirect('/login/') rep.delete_cookie("is_login") return rep # 点击注销后执行,删除cookie,不再保存用户状态,并弹到登录页面 def order(request): print(request.COOKIES.get('is_login')) status = request.COOKIES.get('is_login') if not status: return redirect('/login/') return render(request, "order.html")<!--login.html--><!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body> <h3>用户登录</h3><form action="" method="post"> {% csrf_token %} <p>用户名: <input type="text" name="username"></p> <p>密码: <input type="password" name="pwd"></p> <input type="submit"></form> </body></html><!--index.html--><!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><h2>index页面</h2> <a href="/logout/">注销</a> </body></html><!--order.html--><!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><h2>order 页面</h2> <a href="/logout/">注销</a> </body></html>总结
Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是Session。
问题来了,基于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的Cookie就起到桥接的作用。
我们可以给每个客户端的Cookie分配一个唯一的id,这样用户在访问时,通过Cookie,服务器就知道来的人是“谁”。然后我们再根据不同的Cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。
总结而言:Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。
另外,上述所说的Cookie和Session其实是共通性的东西,不限于语言和框架
在Web开发中,使用 session 来完成会话跟踪,session 底层依赖 Cookie 技术
服务器在运行时可以为每一个用户的浏览器创建一个其独享的 session 对象,由于 session 为用户浏览器独享,所以用户在访问服务器的 web 资源时,可以把各自的数据放在各自的 session 中,当用户再去访问该服务器中的其它 web 资源时,其它 web 资源再从用户各自的 session 中取出数据为用户服务

a. 浏览器第一次请求获取登录页面 login。
b. 浏览器输入账号密码第二次请求,若输入正确,服务器响应浏览器一个 index 页面和一个键为 sessionid,值为随机字符串的 cookie,即 set_cookie ("sessionid",随机字符串)。
c. 服务器内部在 django.session 表中记录一条数据。
django.session 表中有三个字段。
d. 浏览器第三次请求其他资源时,携带 cookie :{sessionid:随机字符串},服务器从 django.session 表中根据该随机字符串取出该用户的数据,供其使用(即保存状态)
注意: django.session 表中保存的是浏览器的信息,而不是每一个用户的信息。 因此, 同一浏览器多个用户请求只保存一条记录(后面覆盖前面),多个浏览器请求才保存多条记录。
cookie 弥补了 http 无状态的不足,让服务器知道来的人是"谁",但是 cookie 以文本的形式保存在浏览器端,安全性较差,且最大只支持 4096 字节,所以只通过 cookie 识别不同的用户,然后,在对应的 session 里保存私密的信息以及超过 4096 字节的文本。
request.session["key"] = value执行步骤:
示例
# 设置前先进行数据库迁移# 设置session'''1.生成随机字符串2.把随机字符串放入cookie(sessionid,'随机字符串')3.将数据存入到django_session表中'''def set_session(request): request.session['name'] = 'Hammer' request.session['is_login'] = True return HttpResponse('set session successfuly!')
ps:如果浏览器不删除cookie,那么数据库内会一直使用这一条session记录,直到过期
request.session.get('key')执行步骤:
def get_session(request): name = request.session.get('name') is_login = request.session.get('is_login') print(name, type(name)) # Hammer <class 'str'> print(is_login, type(is_login)) # True <class 'bool'> return HttpResponse('get session successfuly!')def update_session(request): request.session['name'] = 'Hans' print(request.session.get('name')) # Hans return HttpResponse('update session successfuly!')执行步骤:
session 删除,删除整条记录(包括 session_key、session_data、expire_date 三个字段)
request.session.flush()删除 session_data 里的其中一组键值对:
del request.session["key"]执行步骤:
def delte_session(request): # del request.session['is_login'] request.session.flush() return HttpResponse('del session successfuly!')'''urls.py'''from session import views as session_viewsurlpatterns = [ path('session_login/', session_views.login), path('s_index/', session_views.s_index), path('s_logout/', session_views.s_logout),]'''views.py'''def login(request): if request.method == "GET": return render(request, "login.html") username = request.POST.get("username") password = request.POST.get("pwd") user_obj = models.UserInfo.objects.filter(username=username, password=password).first() print(user_obj.username) if not user_obj: return redirect("/session_login/") else: request.session['is_login'] = True request.session['user1'] = username return redirect("/s_index/")def s_index(request): status = request.session.get('is_login') if not status: return redirect('/session_login/') return render(request, "s_index.html")def s_logout(request): # del request.session["is_login"] # 删除session_data里的一组键值对 request.session.flush() # 删除一条记录包括(session_key session_data expire_date)三个字段 return redirect('/session_login/')<!--s_index.html--><!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><h2>session_index 页面{{ request.session.user1 }}</h2><a href="/s_logout/">注销</a></body></html>
# 获取、设置、删除Session中数据request.session['k1']request.session.get('k1',None)request.session['k1'] = 123request.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(数据库和cookie都删)。request.session.flush() 这用于确保前面的会话数据不可以再次被用户的浏览器访问# 设置会话Session和Cookie的超时时间request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。1. 数据库SessionSESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)2. 缓存SessionSESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置3. 文件SessionSESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() 4. 缓存+数据库SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎5. 加密Cookie SessionSESSION_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 = 60 * 60 * 24 * 7 * 2 # Session的cookie失效日期(2周)(默认)SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)