python自动化测试学习笔记-6redis应用

news2024/11/26 0:31:09

上次我们学到了redis的一些操作,下面来实际运用以下。

这里我们先来学习一下什么是cookie和session。

什么是Cookie

其实简单的说就是当用户通过http协议访问一个服务器的时候,这个服务器会将一些Name/Value键值对返回给客户端浏览器,并将这些数据加上一些限制条件。在条件符合时,这个用户下次再访问服务器的时候,数据又被完整的带给服务器。

因为http是一种无状态协议,用户首次访问web站点的时候,服务器对用户一无所知。而Cookie就像是服务器给每个来访问的用户贴的标签,而这些标签就是对来访问的客户端的独有的身份的一个标识,这里就如同每个人的身份证一样,带着你的个人信息。而当一个客户端第一次连接过来的时候,服务端就会给他打一个标签,这里就如同给你发了一个身份证,当你下次带着这个身份证来的时候,服务器就知道你是谁了。所以Cookie是存在客户端的,这里其实就是在你的浏览器中。

Cookie中包含了一个由名字=值(name=value)这样的信息构成的任意列表,通过Set-Cookie或Set-Cookie2HTTP响应(扩展)首部将其贴到客户端身上。

Cookie的分类

这里Cookie主要分为两种:

会话Cookie:不设置过期时间,保存在浏览器的内存中,关闭浏览器,Cookie便被销毁

普通Cookie:设置了过期时间,保存在硬盘上

关于Session

上面我们知道了Cookie可以让服务器端跟踪每个客户端的访问,但是每次客户端的访问都必须传回这些Cookie,如果Cookie很多,这无形地增加了客户端与服务端的数据传输量,而Session的出现正是为了解决这个问题。

同一个客户端每次和服务端交互时,不需要每次都传回所有的Cookie值,而是只要传回一个ID这个ID是客户端第一次访问服务器的时候生成的,而且每个客户端是唯一的。这样每个客户端就有了一个唯一的ID,客户端只要传回这个ID就行了,这个ID通常是NANE为JSESIONID的一个Cookie。所以Session其实是利用Cookie进行信息处理的。

cookie和session的共同之处在于:cookie和session都是用来跟踪浏览器用户身份的会话方式。

cookie和session的区别是:cookie数据保存在客户端,session数据保存在服务器端。

cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session,当然也没有绝对的安全,只是相对cookie,session更加安全

session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用COOKIE

cookie和session各有优缺点,所以将登陆信息等重要信息存放为SESSION;其他信息如果需要保留,可以放在COOKIE中。

实例:

先来验证用session登录的程序,分析:

首先先设计一个登录的程序,生成session写入redis,然后设计一个查询程序,传入session进行校验。

    第一次登录:从my_user表中验证用户是否存在,用户存在且密码正确的场合生成session(规则:(当前时间戳+username))存入redis。

    第二次登录查看:

#1、先验证用户是否登陆,username,session
#2、验证session是否正确,判断和redis里边是否一致
#3、如果一致返回查询结果
#4、如果不一致,提示session非法
#              session不存在,则提示用户未登录
#              session不一致,登陆失败
#在K-V中传入session

以下是常用工具,放在lib目录的tools文件中:

#常用工具
import pymysql,hashlib,time
import redis
from conf import setting
#

#def op_mysql(host,user,passwd,db,sql,port=3306,charset='utf8'):
def op_mysql(sql):
    conn=pymysql.connect(host=setting.MYSQL_HOST,user=setting.USER,passwd=setting.PASSWORD,port=setting.PORT,db=setting.DB,charset='utf8')
    cur=conn.cursor(cursor=pymysql.cursors.DictCursor)
    cur.execute(sql)
    sql_start=sql[:6].upper()
    if sql_start=='SELECT':#取sql的前6位,判断它是什么类型的语句。
        res=cur.fetchall()
    else:
        conn.commit()
        #res='ok'
    cur.close()
    conn.close()
    return res
def op_redis(k,v=None,expired=0,db=0):
#def op_redis(host,passwd,k,v=None,port=6379,db=1):
    #r=redis.Redis(host=host,password=passwd,port=port,db=db)
    r=redis.Redis(host=setting.REDIS_HOST,password=setting.REDIS_PASSWORD,port=setting.REDIS_PORT,db=db)

    if v:
        r.setex(k,v,expired)
        res='ok'
    else:
        #res=r.get(k).decode()#获取不到的时候返回none,none不能直接进行decode操作
        res=r.get(k)
        if res:
            res=res.decode()
        else:
            res='none'
    return res


def md5_password(st:str):#规定传参的类型必须是str类型
    #st = hashlib.md5()
    bytes_st=st.encode()
    m=hashlib.md5(bytes_st)
    return m.hexdigest()

#main.py

import flask,time,hashlib
from lib.tools import  op_mysql,op_redis,md5_password
import json
server=flask.Flask(__name__)
@server.route('/login',methods=['post'])
def login():
    username=flask.request.values.get('name','')
    password=flask.request.values.get('passwd','')
    sql="select * from my_user where username='%s';"%(username)
    if username and password:
        if op_mysql(sql):
            print(op_mysql(sql))
            if password==op_mysql(sql)[0]['passwd']:
                session=md5_password(str(time.time())+username)
                op_redis('session:%s'%username,session,expired=6000,db=2)
                response={'code':200,'msg':'登陆成功','session':session}
            else:
                response={'code':101,'msg':'密码不正确'}
        else:
            response={'code':102,'msg':'用户不存在'}
    else:
        response={'code':103,'msg':'用户名或密码不能为空'}
    return json.dumps(response,ensure_ascii=False)

启动服务后,在postman中调用127.0.0.1:8088/login?name=pei&passwd=123456,执行一个正确的用户登录,:

{"msg": "登陆成功", "code": 200, "session": "28b14dea0c7a668650fbb19f6364f482"}

查看到redis里边已经插入了一个session数据:

下面进行第二部,传入用户名、session,如果验证正确则查询中表中的数据:

@server.route('/getall',methods=['post','get'])
def getall():
    username=flask.request.values.get('name')
    session=flask.request.values.get('session')
    k='session:%s'%(username)
    redis_session=op_redis(k,db=2)
    if username and session:
        if redis_session:
            if redis_session==session:

                sql="select red,blue from seq "
                response = op_mysql(sql)
            else:
                response={'code':101,'msg':'session非法'}
        else:
            response={'code':102,'msg':'未登录'}
    else:
        response={'code':103,'msg':'必填参数为空'}
    return  json.dumps(response,ensure_ascii=False)

以上是在k-v参数中传入session值,如需需要在cookie中传入session,代码如下:

就是把session=flask.request.values.get('session')改为session=flask.request.cookies.get('session')则取值就是在cookie中进行取值了。

@server.route('/getall_cookie',methods=['post','get'])
def getall_cookie():
    username=flask.request.values.get('name')
    session=flask.request.cookies.get('session')
    k='session:%s'%(username)
    redis_session=op_redis(k,db=2)
    if username and session:
        if redis_session:
            if redis_session==session:

                sql="select red,blue from seq "
                response = op_mysql(sql)
            else:
                response={'code':101,'msg':'session非法'}
        else:
            response={'code':102,'msg':'未登录'}
    else:
        response={'code':103,'msg':'必填参数为空'}
    return  json.dumps(response,ensure_ascii=False)

在我们登录购物网站的话,如果勾选记住密码,一般情况下就是在客户端浏览器上添加了cookie,这样用户打开网站后后台会自动校验cookie信息,不用每次都传一次,如下是设置cookie的代码:

要在页面添加cookie需要先response=flask.make_response(),然后response.set_cookie('session',session)set上要添加的cookie信息

@server.route('/login_setcookie',methods=['post'])
def login_setcookie():
    username=flask.request.values.get('name','')
    password=flask.request.values.get('passwd','')
    sql="select * from my_user where username='%s';"%(username)
    if username and password:
        if op_mysql(sql):
            print(op_mysql(sql))
            if password==op_mysql(sql)[0]['passwd']:
                session=md5_password(str(time.time())+username)
                op_redis('session:%s'%username,session,expired=6000,db=2)
                response=flask.make_response()
                response.set_cookie('session',session)
                msg={'code':200,'msg':'登陆成功','session':session}
            else:
                msg={'code':101,'msg':'密码不正确'}
        else:
            msg={'code':102,'msg':'用户不存在'}
    else:
        msg={'code':103,'msg':'必填参数为空'}
    return response

添加cookie后,我们在调用getall_cookie时只传入name,就能直接获取到seq表中的数据了。

补充:

mysql注入原理

上述代码中存在的sql语句如下:

sql="select * from my_user where username='%s';"%(username)

在获取username时,由于存在‘’,所以存在漏洞;

我们知道‘1’=‘1’是恒为真的,我们可以通过‘’,来模拟制造出这种恒等式,使sql在执行时跳过一些校验,从而进阶访问系统。

当我们输入name=“' or '1'='1”

我们将上述name的值带入sql如下:

sql="select * from my_user where username='' or '1'='1';"

我们在sqlyog中my_user表中执行这个语句,查询出了所有的用户信息,

在一些查询操作中,很容易产生漏洞,造成信息的泄露。

还有一种注入方式是:username="' show tabales ; --"

sql="select * from my_user where username='' show tabales ; --';"

sql语句中--表示注释掉后边的语句,这样就查询出了所有的表,可以对数据库随意进行操作。

为了防止sql的注入,在编写sql的时候我们尽量避免使用‘’,写成如下方式:

sql="select * from my_user where username=%s;",username

这样在传参的时候,可以直接传到输入的参数进行取值,例如:

def op_mysql_new(sql,*data):#第一个是位置参数,第二个是可变参数
    cur.execute(sql,data)
    #data是一个元祖,*data获取出所有传过去的参数
    print(cur.fetchall())
sql="select * from users where name=%s and passwd=%s;"
name='pei'
passwd='123456'
op_mysql_new(sql,name,passwd)

###################################################33

传参:
def test(a,b):
    print(a,b)

li=[1,2]
test(*li)#一个星代表把list里边的数据穿进去
d={'a':'123','b':'456'}
test(**d)#两个星代表从字典里边的数据传进去

最后:下方这份完整的【软件测试】视频学习教程已经整理上传完成,朋友们如果需要可以自行免费领取 【保证100%免费】

在这里插入图片描述

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

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

相关文章

ArcGIS土地利用变化出图

一、数据说明 1. lt51190382010144bjc00文件夹:2010年的影像数据存放在此文件夹中。 2. class2015.tif:2015年的土地利用结果数据。 3. 训练样本2010.shp:对2010年影像执行最大似然分类法所使用的训练样本数据。 4. 点位置.txt&#xff1…

剑指 Offer 47. 礼物的最大价值

剑指 Offer 47. 礼物的最大价值 难度:middle\color{orange}{middle}middle 题目描述 在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次…

深度剖析数据在内存中的存储(上)

目录 1. 数据类型介绍 1.1 类型的基本归类 2. 整形在内存中的存储 2.1 原码、反码、补码 2.2 大小端介绍 2.3 一道小题 本章重点 1. 数据类型详细介绍 2. 整形在内存中的存储:原码、反码、补码 3. 大小端字节序介绍及判断 4. 浮点型在内存中的存储解析 正文…

【手把手一起学习】(三) Altium Designer 20 原理图库添加元件

1 添加元件 元件符号是元件在原理图上的表现形式,主要由边框、管脚、名称等组成,原理图库中的元件管脚(顺序,间距等)与电子元件实物的引脚严格对应,绘制原理图库时,一定参考元件规格书和芯片数据手册中的说明&#xf…

狂飙吧,Lifecycle与协程、Flow的化学反应

前言 协程系列文章: 一个小故事讲明白进程、线程、Kotlin 协程到底啥关系?少年,你可知 Kotlin 协程最初的样子?讲真,Kotlin 协程的挂起/恢复没那么神秘(故事篇)讲真,Kotlin 协程的挂起/恢复没那么神秘(原理…

Elasticsearch:使用 pipelines 路由文档到想要的 Elasticsearch 索引中去

路由文件 当应用程序需要向 Elasticsearch 添加文档时,它们首先要知道目标索引是什么。在很多的应用案例中,特别是针对时序数据,我们想把每个月的数据写入到一个特定的索引中。一方面便于管理索引,另外一方面在将来搜索的时候可以…

从0开始学python -37

Python3 错误和异常 作为 Python 初学者,在刚学习 Python 编程时,经常会看到一些报错信息,在前面我们没有提及,这章节我们会专门介绍。 Python 有两种错误很容易辨认:语法错误和异常。 Python assert(断…

C语言实现用堆解决 TOP-K 问题

目录 TopK函数实现 如何测试 完整源码 生活中我们经常能见到TopK问题,例如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。 所以,TopK问题即求出一组数据中前K个最大或最小的元素,一般情况下,数据量都…

[ Java ] 时间API在更新,传奇已经谢幕,但技术永远不死

(Bill Joy(左一),Vinod Khosla(左二),Andy Bechtolsheim(右二),Scott McNealy(右一) ) CSDN 博文征集活动(和日期相关的代码和bug):点击这里 各位 “big guys”,这篇博文…

【数据结构】顺序表的深度剖析

🌇个人主页:平凡的小苏 📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情 🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html 🚀数据结构专栏&#xff…

Dart的安装及环境变量配置

本文介绍dart的安装步骤及环境变量配置,以及如何在vscode中进行开发环境配置。一、dart的安装访问dart官网https://dart.cn/,点击网站右上角的获取DART SDK进行下载页面。如下图,选择下载SDK的zip压缩文件。根据自己的操作系统情况选择合适版…

DOM 文档对象模型

目录 一、简介 二、节点Node 三、document 1、简介 2、document对象的原型链 3、部分属性 四、元素节点 1、如何获取元素节点对象 通过document对象来获取已存在的元素节点 通过document对象来创建元素节点 2、原型链 3、通过元素节点对象获取其他节点的方法 五、…

如何备份网站到本地电脑(适用虚拟主机)

一、mysql数据库备份 登陆主机控制面板,点击左侧的数据库。 在数据库管理页面最下方有备份数据库的操作项目。点击【通过SQL文件导入导出】,进入到导出和导入的页面。 选择【导出/备份】这个选项导出。会在在wwwroot目录生成以时间命名的sql文件。 导出…

ADC模数转换器(基于STM32F407)

简介 Analog-to-digital converters(模拟数字转换器),我的STM32F407中内置3个ADC,每个 ADC 有 12 位、10 位、8 位和 6 位可选,ADC 具有独立模式、双重模式和三重模式,对于不同 AD 转换要求几乎都有合适的…

list链表,结点

目录 1.链表 2.list构造函数 3.list的赋值和交换,,assign,swap 4.list大小的操作,size,empty,resize 5.list插入和删除,push_back,pop_back,push_front,pop_front,insert,clear,erase,remove 6.list容器数据存取,front,back 7.list反转…

数字孪生加持,水利水电工程或将实现全生命周期管理

水利水电工程在数字孪生技术的加持,使得建设和运营更加高效和智能化,将工程中各种元素、过程和系统数字化,并建立数字孪生模型,以实现工程建设和运营的智能化管理。数字孪生对水利水电实现对工程建设的全生命周期管理,…

Bean的生命周期和作用域

Bean的生命周期Bean的执行流程:Bean 执行流程:启动Spring 容器 -> 实例化 Bean(分配内存空间,从无到有)-> Bean 注册到 Spring 中(存操作) -> 将 Bean 装配到需要的类中(取…

《计算机网络:自顶向下方法》实验2:常用网络命令的使用

使用Ping实用程序来测试计算机的网络连通性 登录到Windows中。单击开始,然后将鼠标指针移到程序上,再移到Windows系统,然后单击命令提示符。在命令提示窗口键入ping 127.0.0.1。问题1:发送了多少数据包?接受了多少数据包?丢失了多少数据包? 发送了4个数据包;接受了4个数…

JavaScript Web API实战:7个小众技巧让你的网站瞬间提升用户体验

随着技术的日新月异,为开发人员提供了令人难以置信的新工具和API。但据了解,在100 多个 API中,只有5%被开发人员积极使用。 让我们来看看一些有用的Web API,它们可以帮助您将网站推向月球! 1、 截屏接口 Screen Capt…

Blockchain gold经测试完美兼容EVM虚拟机

尽管对于行业人士来说,有关寻找更快更便宜的基础层区块链的对话并不是什么新鲜事。 但随着 Defi Summer 持续一年有余的繁荣增长,更实际的需求——以太坊上高昂的 gas 费用使得开发者时间尤为昂贵。 可以看到的是,作为有着以太坊 CPU 之称的 …