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")
View Code

使用装饰器

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")
View Code

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">
View Code

   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/")
View Code

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.安全性好,数据存在服务端
坏处:
数据都保存在服务端,存储压力比较大
 




posted @ 2018-07-05 21:16  JERD  阅读(1936)  评论(2编辑  收藏  举报