• 从自动化测试的角度来聊聊Cookie和Session
  • 发布于 2个月前
  • 401 热度
    0 评论
cookie和session, 搞IT的并不陌生,面试的时候还经常被问到。搞自动化的时候,经常也会打交道。他们有什么功能,又有何区别呢?
Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。

Cookie和Session都可以理解为存储用户信息的一个存储机制,不过一个是信息存储在客户端一个存储在服务端。

Cookie在我们的日常中也很常见,比如我们在淘宝搜索过某些内容,后期总会收到一些淘宝的相关内容的推送信息,因为获取到了我们的cookie中的内容,就会针对的推送相关的信息。我们理解的广义的cookie分发是通过扩展HTTP协议来实现的。

用户通过浏览器发送请求后,在服务端生成私人数据cookie,存储些用户发送过的信息或者自定义的信息,通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie,存储在浏览器的内存中,下次再发送请求时,由浏览器按照一定的原则在浏览器检查所有存储的cookie,如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置,则把该cookie附在请求资源的HTTP请求头上自动发送给服务器。cookie的内容主要包括:名字,值,过期时间,路径和域。路径与域一起构成cookie的作用范围。若不设置过期时间,cookie存储在浏览器内存上,存储这个cookie浏览器关闭时,则cookies自动销毁。而如果设置了过期时间,则保存在硬盘上,只要在有效期内访问都会有效,到期后自动销毁。

用户第一次访问时根据用户需求,在服务端开辟一块内存session保存用户私人信息,然后将这块内存的sessionid发送通过cookie文件发送给浏览器,该cookie保存在浏览器内存中,也就是所说的会话cookie,用户关闭浏览器,则会话cookie销毁,用户使用浏览器再次发送请求时,会自动将内存的id发送给服务器,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id),如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(检索不到,会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id。
一般cookie是明文的,session是加密了的。
所以就会有人用cookie来做文章,利用你的cookie,来伪造cookie,这就是后话。

以下就是在windows下获取cookie信息的实现:
# coding:utf8import os, sysimport sqlite3import win32cryptimport os, shutildef mymovefile(srcfile, dstfile):
    if not os.path.isfile(srcfile):
        print("%s not exist!" % (srcfile))    else:
        fpath, fname = os.path.split(dstfile)  # 分离文件名和路径
        if not os.path.exists(fpath):
            os.makedirs(fpath)  # 创建路径
        shutil.move(srcfile, dstfile)  # 移动文件
        print("move %s -> %s" % (srcfile, dstfile))def mycopyfile(srcfile, dstfile):
    if not os.path.isfile(srcfile):
        print("%s not exist!" % (srcfile))    else:
        fpath, fname = os.path.split(dstfile)  # 分离文件名和路径
        if not os.path.exists(fpath):
            os.makedirs(fpath)  # 创建路径
        shutil.copyfile(srcfile, dstfile)  # 复制文件
        print("copy %s -> %s" % (srcfile, dstfile))
srcfile = '/Users/xxx/git/project1/test.sh'dstfile = '/Users/xxx/tmp/tmp/1/test.sh'google_path = r'Google\Chrome\User Data\Default\Login Data'db_file_path = os.path.join(os.environ['LOCALAPPDATA'], google_path)
print(os.environ['LOCALAPPDATA'])
path_dir = "E:\work\Login Data"mymovefile(db_file_path, path_dir)
conn = sqlite3.connect(path_dir, timeout=10)
cursor = conn.cursor()
cursor.execute('select username_value, password_value, signon_realm from logins')# 接收全部返回结果for data in cursor.fetchall():
    passwd = win32crypt.CryptUnprotectData(data[1], None, None, None, 0)    if passwd:
        print('-------------------------')
        print('username: ' + data[0])
        print('passowrd: ' + (passwd[1]).decode())
        print('websiteURL: ' + data[2])
conn.commit()
conn.close()
二者之间的区别
cookie和session的比较

一、对于cookie:
①cookie是创建于服务器端
②cookie保存在浏览器端
③cookie的生命周期可以通过cookie.setMaxAge(2000);来设置,如果没有设置setMaxAge,
则cookie的生命周期当浏览器关闭的时候,就消亡了
④cookie可以被多个同类型的浏览器共享 可以把cookie想象成一张表

比较:
①存在的位置
cookie 存在于客户端,临时文件夹中
session:存在于服务器的内存中,一个session域对象为一个用户浏览器服务

②安全性
cookie是以明文的方式存放在客户端的,安全性低,可以通过一个加密算法进行加密后存放
session存放于服务器的内存中,所以安全性好

③网络传输量
cookie会传递消息给服务器
session本身存放于服务器,不会有传送流量

④生命周期(以20分钟为例)
(1)cookie的生命周期是累计的,从创建时,就开始计时,20分钟后,cookie生命周期结束,
(2)session的生命周期是间隔的,从创建时,开始计时如在20分钟,没有访问session,那么session生命周期被销毁
但是,如果在20分钟内(如在第19分钟时)访问过session,那么,将重新计算session的生命周期
(3)关机会造成session生命周期的结束,但是对cookie没有影响

⑤访问范围
session为一个用户浏览器独享
cookie为多个用户浏览器共享

上面写了一堆,不是那么好理解,好了,用个生活中的例子,就容易理解了。假如访客要拜访某个公司,先要去前台登记,如果出入频繁,要反复登记。如果人多,效率低。
如果前台妹妹说,先登记姓名,电话等信息,将这些信息放入一个IC门禁卡里面,然后你一天内可以拿着这张门禁卡,反复出入大门,无需反复登记。这张卡就是cookie.
如果这个公司保密工作做得好,每次进入内部,保安还需要检查一下,你是否带有摄像头的手机?你是否带了U盘?但是如果在很短时间内进出,保安要反复的检查你,他也很烦。保安说,你在一个小时内,凭借临时门禁卡,报卡号,他比对卡号后,进出有效。这就是session。

好了,来看一个实际中的例子
在做UI自动化的时候,如果我们保存了cookie,那么再次进入的时候,就可以免登陆了。
driver.add_cookie()driver.get_cookie(name)
在API中,用request的session,也可以实现免登陆。
import requests
s = requests.session()
s.verify = Falseheaders = {        "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1"
    }
data = {aa=xx,auth={username,password}}# 这里可以是模拟登陆的步骤s.post(headers,data)
cookies = requests.utils.dict_from_cookiejar(s.cookies)with open("cook.txt", "w") as fp:
    json.dump(cookies, fp)
print(cookies)
然后后面的请求,都无需登陆了。

但是我最近做自动化的时候,碰到一个难题,就是如果全用UI来做,步骤很复杂。
看登陆,都不是一个页面,一个框子。

如果用API来做,就是登陆的时候不好处理,各种redirect to。

但是发送简单。
如果单独发,说没有authorize,就是还是缺少登陆.
有没有一种可能,就是结合UI和API,用UI登陆,获取cookie。API直接用这个cookie。
答案是肯定的,我尝试成功了。
先登陆,获取cookie:
 def login(self):        
     self.open_url()
     self.type(self.user_name_btn, self.user_name)        
     self.clickat(self.next_btn)        
     self.type(self.user_pwd_btn, self.user_password)        
     self.clickat(self.next_btn)        
     self.clickat(self.next_btn)
     cookies = driver.get_cookies()
      home_cookies = ""
      for cookie in cookies:
          print(cookie)            
          if cookie['name'] == ".AspNet.Cookies" and cookie['domain'] in driver.current_url:
              print("find")
              print(cookie['name'])
              print(cookie['value'])
              home_cookies= cookie['name'] + "="+cookie['value']                
              break
然后可以用API发出去了。
headers = {'content-type': "application/x-www-form-urlencoded",                   
           'Cookie':home_cookies
                   }
        basic_data = {"studentId": self.member_id,            
                      "stageId": self.target_stage,            
                      "grade": 90
        }
        s = requests.session()
        s.verify = False
        response = s.post(url=self.check_url, data=basic_data, headers=headers)        
        print(response.content)        
        if (response.json()["IsSuccess"]):            
            print("success!")        
        else:            
            print("fail, please check!")        
        return response

当然你还可以把代码整得漂亮一点,整个cache来检测一下cookie是否过期,是否需要重新登陆。
用户评论