小白IT:Django框架—cookie和session

一、会话跟踪

1.什么是会话

会话,可以理解为客户端与服务器之间的一次会晤,在一次会晤中可能包含多次的请求和响应,直到这次会晤结束,这整个过程就是一次会话。

比如你访问浏览器,浏览器客户端向某一服务器发出第一个请求开始,会话就开始了,直到客户关闭了浏览器会话结束。

在一个会话中的多个请求中共享数据,就是会话跟踪技术,例如:

  • 请求银行主页;
  • 请求登录(请求参数是用户名和密码);
  • 请求转账(请求参数与转账相关的数据);
  • 请求信誉卡还款(请求参数与还款相关的数据)。

在上述会话中,当前用户信息在这次会话中是共享的,登录的人和转账以及还款的人一定是相同的,也就是再一次会话中我们要实现数据共享的能力,**但是我们知道http协议是无状态和无连接的,**这个时候就需要别的机制来实现,也就是cookie技术。

二、cookie

1.Cookie的简介

我们知道HTTP协议是无状态的。

所谓无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况。

也就是说浏览器的请求对服务器来说,每次都是新的。

状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留。会话中产生的数据又是我们需要保存的,也就是说要“保持状态”。因此Cookie就是在这样一个场景下诞生。

2.cookie工作原理

cookie是浏览器的技术,Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。

cookie的工作原理是:浏览器访问服务端,带着一个空的cookie,然后由服务器产生内容,浏览器收到相应后保存在本地;当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie的内容来判断请求者是“谁”。

cookie的查看方式

使用chrome浏览器,F12打开开发者工具,查看cookie

在这里插入图片描述

cookie的工作图解

在这里插入图片描述

  • Cookie大小上限为4KB;
  • 一个服务器最多在客户端浏览器上保存20个Cookie;
  • 一个浏览器最多保存300个Cookie,因为一个浏览器可以访问多个服务器。
Cookie与HTTP头

Cookie是通过HTTP请求和响应头在客户端和服务器端传递的:

  • Cookie:请求头,客户端发送给服务器端;
  • 格式:Cookie: a=A; b=B; c=C。即多个Cookie用分号离开;  Set-Cookie:响应头,服务器端发送给客户端;
  • 一个Cookie对象一个Set-Cookie: Set-Cookie: a=A Set-Cookie: b=B Set-Cookie: c=C
Cookie的覆盖

如果服务器端发送重复的Cookie那么会覆盖原有的Cookie。

例如客户端的第一个请求服务器端发送的Cookie是:Set-Cookie: a=A;第二请求服务器端发送的是:Set-Cookie: a=AA,那么客户端只留下一个Cookie,即:a=AA。

关于cookie理解:

一个浏览器客户端并一个服务端对应一组cookie,多账号会覆盖。

意思是说,如果你使用同一个浏览器,登录一个帐号访问一个网址,只有一组cookie,如果你登录另外一个帐号访问这个网址,那么也只能存在一组cookie,后面登录的cookie会把之前的cookie顶替掉。

3.Django中操作cookie

Ctrl + Shift + del三个键来清除页面缓存和cookie,将来这个操作你会用的很多

获取cookie方法
request.COOKIES['key']  # 通过键获取cookies中的某个值
request.COOKIES.get('key')  # 推荐
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

参数说明:

  • default: 默认值
  • salt: 加密盐
  • max_age: 后台控制过期时间
设置cookie方法

cookie设置需要通过HttpResponse响应对象调用set_cookie方法来给cookie添加数据。

response = HttpResponse(...)  # 或者 response = render(request,...)

# 设置不加盐cookie内容
response.set_cookie(key,value)

# 设置加盐cookie内容
response.set_signed_cookie(key,value,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获取(不是绝对,底层抓包可以获取到也可以被覆盖)
删除cookie方法

删除cookie是通过HttpResponse对象调用delete_cookie方法删除

def logout(request):
    response = redirect("/login/")  # 获取响应对象
    response.delete_cookie("user")  # 删除用户浏览器上之前设置的usercookie值
    return repsonse

4.cookie带装饰器的登录验证

url.py文件
from cookie_lesson import views

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login,name="login"),
    url(r'^home/', views.home,name="home"),
    url(r'^logout/', views.logout,name="logout"),
]
home.html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>欢迎来到主页</h1>
<a href="{% url 'logout' %}">
    注销
</a>

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script></script>
</body>
</html>
login.html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>登录界面</h1>
<form action="{% url 'login' %}" method="post">
    {% csrf_token %}
    用户名:<input type="text" name="username">
    密码:<input type="password" name="password">
    <input type="submit">

</form>

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script></script>
</body>
</html>
views.py文件
def auth(func):
    """定义装饰器,来对每个操作验证是否登录"""
    def wrapper(request):
        if request.method == "GET":
            # 获取cookie中的数据,如果有而且与服务端发送的cookie数据一致,就通过验证,无需重新登录,直接访问
            is_login = request.COOKIES.get('is_login')
            username = request.COOKIES.get('user')
            if is_login == 'True' and username == "alex":
                ret = func(request)
                return ret
            return redirect('login')  # 如果发现cookie中没有,则跳转登录页面
    return wrapper

def login(request):
    """登录函数"""
    if request.method=="GET":
        return render(request,'login.html')
    else:
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username == "alex" and password == "alex":  # 验证账号密码
            ret = render(request,'home.html')
            # 登录成功后,添加cookie数据返回客户端
            ret.set_cookie("is_login",True)
            ret.set_cookie("user",username)
            return ret
        else:
            return redirect('login')

@auth
def home(request):
    """展示主页,登录状态能访问"""
    return render(request, "home.html")

@auth
def logout(request):
    """注销,登录状态能访问"""
    res = redirect('login')
    res.delete_cookie('is_login')
    res.delete_cookie('user')
    return res

三、session

1.session的由来

Cookie虽然在一定程度上解决了“保持状态”的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能被拦截或窃取。

因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是Session。

由于HTTP协议的无状态特征,服务器根本就不知道访问者是“谁”,我们仍需要cookie来起到桥接作用。

工作原理

我们可以给每个客户端的Cookie分配一个唯一的id,这样用户在访问时,通过Cookie,服务器就知道来的人是“谁”。然后我们再根据不同的Cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。

cookie和session区别

Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie以文本的形式保存在本地,自身安全性较差;

通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。

2.Django中的session

在Django框架中,DJango框架已将cookie和session的数据封装好,存储在自己的数据库中的Django_session表中。

在这里插入图片描述

session的相关方法

django将session的数据封装在request请求体中,注意session_id是Django帮我们自动生成的随机字符串。

获取session方法
request.session['key'] 
request.session.get('key',None)

从cookie里面将sessionid的值取出来,将django-session表里面的对应sessionid的值的那条记录中的session-data字段的数据给你拿出来(并解密)

设置session值
request.session['key'] = 123  # 给session添加键值对数据
request.session.setdefault('key',123)  # 如果键存在,不设置,不存在设置键值对

django-session这个表,你不能通过orm来直接控制,因为你的models.py里面没有这个对应关系

删除session值
  • del request.session[‘key’] :django-session表里面同步删除
  • request.session.delete():仅删除当前会话的所有django_session表中的数据,不常用
  • request.session.flush():删除当前的会话django_session表中数据并删除会话的Cookie,常用
session的其他方法
  • request.session.session_key :获取session_id的值
  • request.session.keys():获取数据库中session的所有键
  • request.session.values():获取数据库中session所有的值
  • request.session.items():获取数据库中session数据的所有键值对
  • request.session.clear_expired():删除数据库中过期的session数据
  • request.session.set_expiry(value):设置会话的超时时间。
    • value:整数,表示多少秒失效;datetime表示到该时间失效;0表示关闭浏览器就失效;None,依赖全局session失效。

3.Session版登陆验证实例

这里只展示views.py文件的代码,其他与模板文件和url配置与前面cookie版相同。

思路:我们平时访问页面,必须先登录,正常登陆会跳转到home页面。但是有一种情况,有人会直接访问index页面,比如淘宝的购物车,没有登录时去结算,会跳转到登录页面。

如果没有登录直接访问index页面,我们让他直接跳转到登录页面,这个时候如果用户正常登陆成功,我们应该是直接跳转到他之间想要访问的index页面,对不对。

就好比你淘宝去登录成功了,就是直接跳到了结算页面,并不需要你再去点结算页面。

这样用户体验才会比较舒服。

views.py文件

Views.py

4.Django中的session相关设置

  1. 数据库Session

    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
    
  2. 缓存Session

    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
    
  3. 文件Session

    SESSION_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 Session

    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
    
  6. 其他共用设置

    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,默认修改之后才保存(默认)
    

5.CBV模式添加装饰器

CBV添加装饰器的方式:视图函数中已经学习过。

  1. 加在CBV视图的某个方法上,如get或post方法上。
  2. 加在dispatch方法上,为所有函数加上装饰器,注意执行父类的dispatch方法,并返回。
  3. 加在视图类上,但method_decorator必须传 name 关键字参数。

需要导入一个装饰器方法

from django.utils.decorators import method_decorator
项目实践

一个完整的url路由分发,装饰器验证登录的通过CBV模式实现的登录验证项目

项目下总路由分发文件urls.py

from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^CBV_decoration', include("CBV_decoration.urls")),  # include路径分发到应用CBV_decoration下的urls
]
应用CBV_decoration下的urls文件
from django.conf.urls import url
from CBV_decoration.views import Logout,Login,Home,Index

urlpatterns = [
    url(r'/login/', Login.as_view(),name="login"),  # 登录页面url
    url(r'/home/', Home.as_view(),name="home"),  # home页面url
    url(r'/index/', Index.as_view(),name="index"),  # index页面url
    url(r'/logout/', Logout.as_view(),name="logout"),  # 注销url
]
应用CBV_decoration下的views.py
from django.shortcuts import render,redirect,HttpResponse
from django.views import View
from django.utils.decorators import method_decorator
from functools import wraps

# Create your views here.

def auth(func):
    """定义装饰器,来对每个操作验证是否登录"""
    def wrapper(request,*args,**kwargs):
        if request.method == "GET":
            next_url = request.get_full_path()
            if request.session.get('user'):  # 如果拿到了用户,说明已经登录,直接允许访问想要访问的页面
                ret = func(request,*args,**kwargs)
                return ret
            else:  # 如果没有登录,存下想要访问的url,让他先去登录
                return redirect('CBV_decoration/login/?next={}'.format(next_url))  # 如果发现cookie中没有取到用户,则跳转登录页面,并且将想要访问的路径封装在get请求的url中
    return wrapper

class Login(View):
    """登录函数"""

    def get(self,request):
        return render(request,'login.html')

    def post(self,request):
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username == "alex" and password == "alex":  # 验证账号密码
            request.session['user'] = username
            # 1.生成随机字符串session_id:随机字符串
            # 2.加密用户信息,保存到数据库,Django中保存在Django_session表中
            # 3.将session_id:随机字符串放到cookie发送客户端
            next_url = request.GET.get('next')  # 获取未登录是访问页面的路径
            if next_url:
                # 如果有直接跳转
                return redirect(next_url)
        else:
            # 没有的话正常登录到home页面
            return redirect('home')


class Home(View):
    """展示主页,登录状态能访问"""

    @method_decorator(auth)
    def dispatch(self, request, *args, **kwargs):
        ret = super().dispatch(request, *args, **kwargs)
        return ret

    def get(self,request):
        return render(request, "home.html")


class Index(View):
    @method_decorator(auth)
    def dispatch(self, request, *args, **kwargs):
        ret = super().dispatch(request, *args, **kwargs)
        return ret

    def get(self,request):
        return render(request, "index.html")


class Logout(View):
    """注销,登录状态能访问"""

    @method_decorator(auth)
    def dispatch(self, request, *args, **kwargs):
        ret = super().dispatch(request, *args, **kwargs)
        return ret

    def get(self,request):
        request.session.flush()  # 删除当前的会话数据并删除会话的Cookie
        # request.session.delete()  # 仅仅删除当前会话的所有Session数据
        return redirect('login')
模板template文件夹
login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>登录界面</h1>
<form action="" method="post">  <!--注意action路径不填,提交到当前路径-->
    {% csrf_token %}
    用户名:<input type="text" name="username">
    密码:<input type="password" name="password">
    <input type="submit">

</form>

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script></script>
</body>
</html>
home.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>Home页面</h1>
<a href="{% url 'index' %}">进入首页</a>
<br>
<a href="{% url 'logout' %}">
    注销
</a>

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script></script>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>index页面</h1>
<br>
<a href="{% url 'logout' %}">
    注销
</a>

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script></script>
</body>
</html>

四、jQuery操作cookie

通过jQuery获取cookie的数据,添加或者删除cookie键值对。

使用之jQuery操作cookie需要引入jQuery.cookie.js插件,而jQuery.cookie.js基于jQuery;

jQuery.cookie.js下载路径:http://plugins.jquery.com/cookie/

<script src="{% static 'jquery/3.4.1/jquery.js' %}"></script>  <!--导入jQuery-->

<script src="{% static 'jquery.cookie.js' %}"></script>  <!--引用jquery操作cookie的插件-->
1.添加一个cookie会话键值对
$.cookie('key','value')

这里没有指明 cookie有效时间,所创建的cookie有效期默认到用户关闭浏览器为止,所以被称为 “会话cookie(session cookie)”。

2.创建有效期的cookie
$.cookie('key', 'value', { expires: 7 });

这里指明了cookie有效时间,所创建的cookie被称为“持久 cookie (persistent cookie)”。注意单位是:天;

3.创建cookie并设置cookie的有效路径
$.cookie('key', 'value', { expires: 7, path: '/' });

在默认情况下,只有设置 cookie的网页才能读取该 cookie。

如果想让一个页面读取另一个页面设置的cookie,必须设置cookie的路径。cookie的路径用于设置能够读取 cookie的顶级目录。

将这个路径设置为网站的根目录,可以让所有网页都能互相读取 cookie (一般不要这样设置,防止出现冲突)。

4.读取cookie
$.cookie('key');
5.删除cookie
$.cookie('the_cookie', null);   //通过传递null作为cookie的值即可
6.可选参数
  • expires:(Number|Date)有效期;设置一个整数时,单位是天;也可以设置一个日期对象作为Cookie的过期日期;
  • path:(String)创建该Cookie的页面路径;
  • domain:(String)创建该Cookie的页面域名;
  • secure:(Booblean)如果设为true,那么此Cookie的传输会要求一个安全协议,例如:HTTPS;
$.cookie('key','value',{
    expires:7, 
    path:'/',
    domain:'jquery.com',
    secure:true
}) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值