Cookie与Session 以及给CBV添加装饰器

news2025/7/18 8:19:09

文章目录

    • Cookie与Session
      • 1、Django操作cookie
        • 简单实现用户登录
        • 加入装饰器
      • 2、Django操作session
        • 设置session
        • 获取session
        • 过期时间
        • 清除session
    • CBV添加装饰器

Cookie与Session

HTTP被设计为”⽆态”,也就是俗称“脸盲”。 这⼀次请求和下⼀次请求 之间没有任何状态保持,我们⽆法根据请求的任何⽅⾯(IP地址,⽤户代理等)来识别来自同⼀ 个⼈的连续请求。

实现状态保持的⽅式:在客户端或服务器端存储与会话有关的数据 (客户端与服务器端的⼀次通信,就是⼀次会话)

  • cookie
  • session

不同的请求者之间不会共享这些数据,cookie和session与请求者⼀⼀对应

"""
发展史:
	1.网站没有保存用户功能的需求,所有用户访问返回的结果都是一样的	eg:新闻,博客,文章
	
	2.出现了一些需要保存用户信息的网站
		eg:淘宝,支付宝,京东.....
		
	以登录功能为例子,如果不保存用户登陆状态,也就意味着用户每次访问网站都需要重复的输入用户名和密码(这样的网站你还想用吗?)
	当用户第一次登录成功之后,将用户的密码返回给用户浏览器,让用户浏览器保存在本地,之后访问网站的时候浏览器会自动将保存在浏览器上的用户名和密码发送给服务端,服务端获取之后,自动校验。
	早期这种方式具有很大的安全隐患,
	
	
	优化:
		当用户登录成功之后,服务端产生一个随机字符串(在服务端保存数据,用Kv键值对的形式),交由客户端浏览器保存,
		
		随机字符串1:用户1的相关信息
		随机字符串2:用户2的相关信息
		随机字符串3:用户3的相关信息
		
		之后访问服务端的时候,都带着该随机字符串,服务端去数据库中比对是否有对应的随机字符串,从而获取到对应的用户信息
		
但是如果拿到了随机字符串,那么就可以冒充当前用户,其实还存在安全隐患


在web领域,没有绝对的安全,也没有绝对的不安全
		
			
"""
cookie 	
	服务端保存在客户端浏览器上的信息都可以称之为cookie
    它的表现形式一般都是k:v键值对(可以有多个)
session
	数据是保存在服务端的,并且它的表现形式一般都是k:v键值对(可以有多个)
token
	session虽然数据保存在服务端,但是禁不住数据量大
    服务端不再保存数据,而是在登录成功之后,将一段信息进行加密处理,(加密算法只有自己知道),将加密后的结果拼接在信息后面,整体返回给浏览器保存,浏览器下次再访问的时候带着该信息,服务端自动切取前面一段信息,再次使用自己的加密算法跟浏览器尾部的密文进行比对

jwt认证
	
 
"""总结"""
	1.cookie是保存在客户端浏览器上的信息
    2.session就是保存在服务端上的信息
    3.session是基于cookie工作的(大部分的保存用户状态的操作都需要使用到cookie)

1、Django操作cookie

#虽然cookie是服务端告诉客户端需要保存的内容
#但是客户端可以选择拒绝保存,禁止了之后只要是需要记录用户状态的网站登录功能都无法使用

在这里插入图片描述

# 视图函数的返回值
return HttpResponse()
return render()
return redirects()

#如果想要操作cookie,就必须利用obj对象,不能再像之前那样写视图函数的返回值了
obj1=HttsResponse()
return obj1
obj2=render()
return obj2
obj3=redirect()
return obj3


"""设置cookie"""
	obj.set_cookie(key,value='')
"""获取cookie"""
	request.COOKIES.get(key)
    request.get_signed_cookie(key, default=RAISE_ERROR, salt='盐', max_age=None)
"""设置超时时间"""
	在设置cookie的时候,可以添加超时时间
    obj.set_cookie('username', 'zs666', max_age=5, expires=3)
    
    max_age
    expires
    	两者都是设置超时时间,都是以秒为单位,
        需要注意的是针对IE浏览器需要使用expires
"""删除cookie"""
obj.delete_cookie('username')

"""加盐"""
obj.set_sifned_cookie(key,value,salt='盐')

简单实现用户登录

def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'zhao' and password == '123':
            # 保存用户登录状态
            obj = redirect('home')
            # 让浏览器记录cookie数据
            obj.set_cookie('username', 'zs666')
            """
            浏览器不单单会帮你存,而且每次访问的时候都会带着它
            """
            # 跳转到一个需要用户登录才能看到的页面
            return obj
    return render(request, 'login.html')


def home(request):
    # 获取cookie信息,进行判断
    if request.COOKIES.get('username') == 'zs666':
        return HttpResponse('我是Home页面,只有登录的用户才可进来')
    # 没有登录应该跳转到登录页面
    return redirect('login')

加入装饰器

"""
用户如果再没有登录的情况下,想访问一个需要登录的页面,那么先跳转到登录页面,
当用户输入正确的用户名和密码之后,
应该跳转到用户之前想到访问的页面,而不是直接写死
"""


# 校验用户是否登录的装饰器
def login_auth(func):
    def inner(request, *args, **kwargs):
        target_url = request.get_full_path()
        if request.COOKIES.get('username'):
            res = func(request, *args, **kwargs)
            return res
        else:
            return redirect('/login/?next=%s' % target_url)

    return inner


def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'zhao' and password == '123':
            # 获取用户上一次想要访问的url
            target_url = request.GET.get('next')
            if target_url:
                obj = redirect(target_url)
            else:
                # 保存用户登录状态
                obj = redirect('home')
                # 让浏览器记录cookie数据
            obj.set_cookie('username', 'zs666')
            """
            浏览器不单单会帮你存,而且每次访问的时候都会带着它
            """
            # 跳转到一个需要用户登录才能看到的页面
            return obj
    return render(request, 'login.html')


@login_auth
def home(request):
    # 获取cookie信息,进行判断
    # if request.COOKIES.get('username') == 'zs666':
    #     return HttpResponse('我是Home页面,只有登录的用户才可进来')
    # 没有登录应该跳转到登录页面
    # return redirect('login')
    return HttpResponse('我是Home页面,只有登录的用户才可进来')


@login_auth
def index(request):
    # return redirect('login')
    return HttpResponse('我是index页面,只有登录的用户才可进来')


@login_auth
def func(request):
    return HttpResponse('我是func页面,只有登录的用户才可进来')


# 注销,删除cookie
@login_auth
def logout(request):
    obj = redirect('login')
    obj.delete_cookie('username')
    return obj

2、Django操作session

session数据保存在服务端,给客户端返回的是一个随机字符串
	sessionid:随机字符串	
1.默认情况下操作session的时候需要Django默认的一张django_session表
	数据库迁移命令
    	django会自动的创建多张表,django_session就是其中的一张
"""设置session"""
request.session['key'] = value
"""获取session"""
request.session.get('key')
"""设置过期时间"""
request.session.set_expiry()
	括号内可以放四种类型的参数
    	1.整数   				多少秒
        2.日期对象   			到指定日期就失效
        3. 0 				  一旦当前浏览器窗口关闭立刻失效
        4. 不写				失效时间取决于django内部全局session默认的的失效时间(14天)
"""清除session"""
	request.session.delete() #只删服务端的session,客户端的不删
	request.session.flush() #浏览器和服务端都清空
 


2.session是保存在服务端的,但是session的保存位置可以有多种选择
	1.MySQL
    2.文件
    3.redis
    4.memcache
    ......
	
    
django_session表中的数据条数,是取决于浏览器的
	同一个计算机上(IP地址),同一个浏览器只会同时有一条数据生效
    (当session过期的时候,可能会出现多条数据对应一个浏览器,但是该现象不会持续很久,内部会自动识别过期的数据清除,也可以手动通过代码清除)
    主要是为了节省服务端数据库资源
    

先执行数据库迁移的两条命令,查看django_session表结构

如果没有先执行数据库迁移命令,那么会报(no such table:django_session)错误

在这里插入图片描述

设置session

def set_session(request):
    # 设置session
    request.session['hobby'] = 'JayChou'
    """
    设置session内部发生了那些事?
        1.django内部会自动生成一个随机字符串
        2.django内部自动将随机字符串和后面对应的数据存储到django_session表中(这一步不是直接生效的,)
            2.1先在内存中产生操作数据的缓存
            2.2在响应结果django中间件的时候才真正的操作数据
        3.将产生的随机字符串返回个客户端浏览器保存
    """

    return HttpResponse('稻香')

然后在浏览器输入路由,回车后,django_session表中会自动生成数据,

expire_data字段是过期时间
在这里插入图片描述


session给客户端返回的是一个随机字符串,随机字符串指的就是django_session表中的session_key

django默认的session过期时间是14,但是也可以认为的修改

在这里插入图片描述

获取session

def get_session(request):
    # 获取session
    print(request.session.get('hobby'))
    """
    获取session发生了那些事:
        1.自动从浏览器请求中获取sessionid对应的随机字符串
        2.拿着该随机字符串去django_session表中查找对应的数据,
        3.如果比对上了,则将对应的数据取出并以字典的形式封装到request.session中
            比对不上,则request.session.get()返回None
    """
    return HttpResponse('haha')

在这里插入图片描述


过期时间

request.session.set_expiry()
	括号内可以放四种类型的参数
    	1.整数   				多少秒
        2.日期对象   			到指定日期就失效
        3. 0 				  一旦当前浏览器窗口关闭立刻失效
        4. 不写				失效时间取决于django内部全局
def set_session(request):
    # 设置session
    request.session['hobby'] = 'JayChou'
    # 设置超时时间
    request.session.set_expiry(0) # 浏览器关闭就失效
    return HttpResponse('稻香')

def get_session(request):
    # 获取session
    # print(request.session.get('hobby'))
    if request.session.get('hobby'):
        print(request.session.get('hobby'))
        return HttpResponse('haha')
    return HttpResponse('浏览器窗口关闭过了,得不到session数据')

清除session

def del_session(request):
    request.session.delete() ##只删服务端的session,客户端的不删
    return HttpResponse("删除")



推荐使用request.session.flush() #浏览器和服务端都清空

在这里插入图片描述

CBV添加装饰器

  • 装饰器
# 校验用户是否登录的装饰器
def login_auth(func):
    def inner(request, *args, **kwargs):
        target_url = request.get_full_path()
        if request.COOKIES.get('username'):
            res = func(request, *args, **kwargs)
            return res
        else:
            return redirect('/login/?next=%s' % target_url)

    return inner
  • 添加装饰器 方式一
# views.py
from django.views import View
from django.utils.decorators import method_decorator

class MyLogin(View):
    @method_decorator(login_auth)#方式一
    def get(self, requset):
        return HttpResponse('get')

    def post(self, reqeust):
        return HttpResponse('post')

    
# urls.py
    path('mylogin/',views.MyLogin.as_view())  
  • 添加装饰器 方式二
# views.py
from django.views import View
from django.utils.decorators import method_decorator

@method_decorator(login_auth, name='get')  # 方式二,可以添加多个,针对不同的方法加不同的装饰器
@method_decorator(login_auth, name='post')
class MyLogin(View):
    def get(self, requset):
        return HttpResponse('get')

    def post(self, reqeust):
        return HttpResponse('post')
    
    
# urls.py
    path('mylogin/',views.MyLogin.as_view())
  • 添加装饰器 方式三
# views.py
from django.views import View
from django.utils.decorators import method_decorator


class MyLogin(View):
    @method_decorator(login_auth)  # 方式三,会直接作用于当前类里的所有方法
    def dispatch(self, request, *args, **kwargs): # 
        pass

    def get(self, requset):
        return HttpResponse('get')

    def post(self, reqeust):
        return HttpResponse('post')
    
    
# urls.py
    path('mylogin/',views.MyLogin.as_view())   

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/8214.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

跨模态神经搜索实践VCED 环境准备

跨模态神经搜索实践 环境准备 本文基于WSL2及docker进行环境搭建 1. 安装和配置WSL2 Ubuntu发行版 1.1 安装WSL2 Ubuntu 相关安装命令: wsl --install:默认安装Ubuntu发行版wsl --list --online:查看可支持的发行版本wsl --install -d &…

如何将 wordfile 添加到 UltraEdit 或 UEStudio

UltraEdit 本身支持开箱即用的最常用编程和标记语言的语法突出显示。我们也有数百个其他语言的 wordfile,但是,很容易找到和添加您需要的语言! 重要提示:此电源提示适用于运行 UltraEdit v15.00或 UEStudio v09.10及更高版本的用户…

Ubuntu18.04系统安装nginx

Ubuntu18.04系统安装nginx一、在线安装 Nginx二、离线安装 Nginx参考链接请确保以具有 sudo 权限的用户身份登录,并且您没有在端口 80 或 443 上运行 Apache 或任何其他 Web 服务器。 一、在线安装 Nginx 简介:Nginx (engine x) 是一个免费的&#xff0…

swift-类属性

了解属性之前,需要先了解前面的swift-类结构内容 - swift-类结构源码探寻 FieldDescriptor TargetClassDescriptor {var Flags: ContextDescriptorFlags // uint32var Parent: TargetRelativeContextPointer // Int32var Name: TargetRelativeDirectPointer // I…

Markdown还能这么玩?这款开源神器绝了!

Markdown是一款轻量级标记语言,由于它易读易写的特性,很多程序员用它来写项目文档。其实Markdown的功能不止于此,结合一些工具使用还可以用来做PPT,今天带大家使用Markdown来做一个PPT,看看到底有多炫酷! S…

《springboot那些事》

注&#xff1a;static目录、主要用于存放非模板引擎渲染的资源。 ​ template目录&#xff0c;存放渲染引擎页面的资源。 一句话&#xff1a;用模板引擎的话&#xff0c;就放template目录、否则static目录。 一、使用thymeleaf 引入thymealeaf坐标 <dependency><…

22.11.15打卡 mysql学习笔记

学了DDL和DQL, 今天课太多, 没怎么学啊, 很烦躁, 还有3周要考试了 空格可以有一个或者多个 if not exists表示不存在则执行, 存在则不执行 方括号当中的都可 create database itcase; show databases;查看数据库 再次创建itcase数据库 加上if not exists就不会报错 字符集演示 …

DPDK LPM库(学习笔记)

1 LPM库 DPDK LPM库组件为32位的key实现了最长前缀匹配&#xff08;LPM&#xff09;表查找方法&#xff0c;该方法通常用于在IP转发应用程序中找到最佳路由匹配。 2 LPM API概述 LPM组件实例的主要配置参数是要支持的最大规则数。 LPM前缀由一对参数&#xff08;32位Key&…

React源码分析3-render阶段(穿插scheduler和reconciler)

本章将讲解 react 的核心阶段之一 —— render阶段&#xff0c;我们将探究以下部分内容的源码&#xff1a; 更新任务的触发更新任务的创建reconciler 过程同步和异步遍历及执行任务scheduler 是如何实现帧空闲时间调度任务以及中断任务的 触发更新 触发更新的方式主要有以下几…

Leetcode第21题:合并两个有序链表

生命无罪&#xff0c;健康万岁&#xff0c;我是laity。 我曾七次鄙视自己的灵魂&#xff1a; 第一次&#xff0c;当它本可进取时&#xff0c;却故作谦卑&#xff1b; 第二次&#xff0c;当它在空虚时&#xff0c;用爱欲来填充&#xff1b; 第三次&#xff0c;在困难和容易之…

面试官:你说说 Mysql 索引失效有哪些场景?

前言 SQL 写不好 加班少不了 日常工作中SQL 是必不可少的一项技术 但是很多人不会过多的去关注SQL问题。 一是数据量小&#xff0c;二是没有意识到索引的重要性。本文主要是整理 SQL失效场景&#xff0c;如果里面的细节你都知道&#xff0c;那你一定是学习能力比较好的人&am…

基于Docker的网络安全靶场搭建

背景介绍 在学习网络安全技术过程中,我们往往需要有一个自己的操作机与多个用来搭建环境的靶机,使用VM虚拟机模拟资源占用较大,成本高、局限性大且使用十分不便。 这时我们可以使用一台安装好Docker环境的linux虚拟机来完成桌面版操作机与WEB靶机的搭建与实验操作。 Docker…

Linux操作系统~进程替换,exec系列函数的使用

目录 1.概念/原理 &#xff08;1&#xff09;.替换原理 &#xff08;2&#xff09;.子进程调用execl执行程序替换&#xff0c;为什么父进程不受影响&#xff1f; &#xff08;3&#xff09;.exec*返回值 2.替换函数exec execl execv execlp execvp的&#xff08;execv…

Android Studio App开发之网络通信中使用POST方式调用HTTP接口实现应用更新功能(附源码 超详细必看)

运行有问题或需要源码请点赞关注收藏后评论区留言~~~ 一、POST方式调用HTTP接口 POST方式把接口地址与请求报文分开&#xff0c;允许使用自定义的报文格式&#xff0c;由此扩大了该方式的应用场景。POST请求与GET请求主要有三处编码差异 1&#xff1a;在调用setRequestMethod方…

Kafka 消息队列 ( 一 ) 基本概念

0.MQ(message queue) 消息中间件 生活中的问题 : 快递员 给 你 送东西, 你必须 在家等着, (效率低) 可以 把东西 放 指定 的 地方(菜鸟驿站) , 你自己去取 , 指定 的地点(菜鸟驿站) 就是 MQ 消息队列中间件 0.1.开发中的问题 0.1.1.异步问题 0.1.2.业务解耦 0.1.3.流量削…

2. 信息在计算机中存储的格式

目录 一、信息存储&#xff1a; 1. 空间大小定义 2. 不同进制的转换方法 3. 各种数据类型所占字节数 4. 字节顺序 5. 字符串存储 6. 代码的二进制表示 7. 布尔代数运算 8. 逻辑运算 9. 移位运算 二、 整数表示 1. 有符号与无符号表示 1.1 表示范围 1.2 补码编码的…

C语言日记 35 拷贝构造函数

书P132&#xff1a; 拷贝构造函数的作用是 用已存在的对象初始化另一对象&#xff0c;两对象类类型应一样 在这里我们可以看到&#xff0c; 他对被拷贝的对象的要求只有“已存在的对象&#xff0c;两对象类类型一样”&#xff0c;也就是说他这里也没有说我们不能跨区域&…

使用 Spring Cloud Loadbalancer 实现客户端负载均衡

使用 Spring Cloud Loadbalancer 实现客户端负载均衡 作者&#xff1a;Grey 原文地址&#xff1a; 博客园&#xff1a;使用 Spring Cloud Loadbalancer 实现客户端负载均衡 CSDN&#xff1a;使用 Spring Cloud Loadbalancer 实现客户端负载均衡 背景 在Spring Cloud G 版…

为什么 think-cell 图表中的标签显示为白色矩形?

有些标签的背景错误地变成白色&#xff0c;或显示幻灯片背景。当前版本的 PowerPoint 不会出现此问题。 •使用 PowerPoint 2007 打开 .ppt 文件并单击标签内部时&#xff0c;将显示正确的标签背景&#xff0c;但是在保存后重新打开该文件时&#xff0c;会返回不正确…

分布式系统的 38 个知识点

天天说分布式分布式&#xff0c;那么我们是否知道什么是分布式&#xff0c;分布式会遇到什么问题&#xff0c;有哪些理论支撑&#xff0c;有哪些经典的应对方案&#xff0c;业界是如何设计并保证分布式系统的高可用呢&#xff1f; 1. 架构设计 这一节将从一些经典的开源系统架…