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




  • 相关阅读:
    mysql中事务隔离级别可重复读说明
    Zookeeper安装与启动
    PHP闭包之bind和bindTo
    使用WebPack打包
    用Python下载momentum中的精美壁纸
    supervisor使用
    Shell脚本:RedisKey批量删除
    使用Certbot配置站点的https
    PHPfmt代码格式化
    创建用私钥签名的证书
  • 原文地址:https://www.cnblogs.com/zgf-666/p/9270542.html
Copyright © 2020-2023  润新知