1、cookie
由来
web基于HTTP,但HTTP是无状态
=>作用:通过存储实现记录状态
,从而引入session和cookie/token
=> 每次HTTP请求都自动带数据给服务器(通过cookie实现)
原理
1、浏览器发送HTTP请求(无状态)给服务端
2、服务端设置cookie(即Set-Cookie)发送给浏览器
字典类型:name和value对
3、浏览器存储cookie(以后发送的请求均自动附加该cookie)
=> cookie即浏览器存储的数据,打开浏览器即可看到=>不安全
浏览器中看到的cookie
cookie核心特点
每次请求都会发送相应cookie到服务器
生成机制
- 服务端生成,在HTTP Response Header 中Set-Cookie
- 客户端生成,通过document.cookie设置
属性
缺陷
cookie初衷用于维持HTTP状态,而非存储数据
大小限制:4K
性能浪费:cookie附带在http请求上,数据量过大,会导致每个http请求非常大=>耗费流量和带宽
2、session
即会话
打开网页即会话的开始(结束模糊)
所以不同网站对每个用户的会话都设定了时间(结束会话的世界)以及唯一ID(sessionID)
- 一般来说,在服务端,session的存储方式有文件方式、数据库方式
- session ID :不是cookie值,是用来识别这个文件的(文件名相关)、识别数据库的某一条记录
=>保存数据库
流程
流程图1、客户端/浏览器发送HTTP请求到服务端
自动将可用的cookie封装在请求头中和请求一起发送(postman或客户端会有该功能,但python不具有)
2、服务端设置session (包括sessionID 和失效时间等),然后通过设置cookie返回给浏览器
3、浏览器存储cookie,之后请求
4、若cookie失效,浏览器一般会自动删除对应cookie,会话结束(用户需要重新输入用户名密码)
对比
序号 | session | cookie |
---|---|---|
相同1 | 服务器生成,存储特定值(键值对) | |
相同2 | 都有生命周期1. 服务器对于session对象的保存最大时间设置 2. 客户端进程是否关闭:仅对该客户端有效,即session仍是有效的
|
都有生命周期1. cookie自身的存活时间:服务器生成cookie时设置的; 2. 客户端是否保留了cookie:仅客户端失效,但cookie仍生效即在其他工具中可用
|
不同1 | 存储服务器 | 返回给客户端一般sessionID会以cookies返回给客户端 且cookie跟随HTTP的每个请求发送出去 |
不同2 | 服务器来识别、操作存储session值的对象 | |
不同3 | session比cookie安全 session是存储服务端的,是不可见的,是不可改变(相对) |
cookie是存储客户端的,是可见的,是可以改变的 |
注:未做状态处理的应用则不会记录登录状态的=>抓包时获取的cookie,有些有用,而有些没有用(可能跟开发设置的作用域有关)
再次打开仍有效,是本地存储
引申:
1、JMeter中添加cookie:
配置元件--HTTP信息头管理器:
需要手动设置
配置元件--HTTP Cookie管理器:
自动存储并在后续作用域中自动使用
3、token
JWT 即json web token
1、登录请求
2、服务端使用JWT 生成JWT签名秘文返回给浏览器
3、浏览器通过cookie或storage存储,每次请求均携带该秘文=>不用再次输入账号密码
=>token存储于用户端
JWT:header、payload、signature三部分
- header:声明签名使用的算法
- payload:特定数据,如有效期
-
signature:签名
JWT原理
4、python设置Cookies
- token:客户端主导,诞生服务器,但保存浏览器
可以放在cookie或storage中,类似令牌,允许访问服务器
4.1 获取cookie
方法1:request请求获取Cookies
# step1:向目标站点发送请求
res=requests.get(url)
# step2:获取响应中的cookies
cookies=res.cookies
print(cookies) # <RequestsCookieJar[]>
方法2:selenium中driver获取Cookies
from selenium import webdriver
import time
driver=webdriver.Chrome()
driver.get(url)
time.sleep(5) # 等待加载,以获取所有cookie
res=driver.get_cookies() # 获取全部cookies
print(res)
"""
[{'domain': 'www.zhipin.com', 'expiry': 1*.785805, 'httpOnly': False, 'name': '_bl_uid', 'path': '/', 'secure': False, 'value': 'Unlb*'},
{'domain': 'www.zhipin.com', 'expiry': 1*.715641, 'httpOnly': False, 'name': 'historyState', 'path': '/', 'secure': False, 'value': 'state'},
……]
"""
driver.quit()
cookie各字段
4.2 保存cookie
方法1:使用pickle库将Cookie保存文件
import pickle
"""
将数据对象转换为二进制形式进行存储,或将二进制形式的数据对象还原为原来的数据对象
Pickle可以将Python中任何数据对象进行序列化和反序列化操作
主要方法:dumps \ loads
- dumps:将数据序列化后存储到文件和内存中
- loads:从文件和内存中将数据反序列化还原为Python数据对象
"""
# 使用Cookies对象保存到文件
with open("cookie.pkl","wb") as f:
pickle.dump(cookies,f) # 数据序列化写入文件
with open("cookie.pkl","rb") as f:
content=pickle.load(f) # 读取数据并反序化
print(content) # UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 0: illegal multibyte sequence
方法2:requests中Session对象来保存Cookie=>前提:response对象的Cookie非空
# requests中session对象=>当前request请求中没有返回Cookies,所以当前方法不适用
import requests
# step1:创建Session对象
session=requests.Session()
# step2:向目标站点发送请求
url = "https://www.zhipin.com/web/geek/job?city=101020100"
response=session.get(url,cookies={'__c': '1692775678'}) #
# TypeError: expected string or bytes-like object => cookies传参:键为cookie的name,值为cookie的value
# step3:获取响应中的Cookies
cookie=session.cookies
print(cookie) # 下次使用cookie时,直接使用Session对象即可
4.3使用cookie
方法1:headers参数中添加Cookie,其值为字符串类型
(键=值,每个键值对间使用;分割),如lastCity=1010201; __g=-; Hm_lvt=16915666
详见上述Session对象
方法2:使用cookies参数,传参类型,键值对
import pickle,requests
# step1:读取之前保存的cookie
with open("cookie.pkl","rb") as f:
cookies=pickle.load(f) # 读取数据并反序化
print(cookies)
# step2:创建Session对象
session=requests.Session()
# step3:将Cookies携带到请求头中
def get_libs():
lib_url="https://www.zhipin.com/wapi/zpgeek/search/joblist.json"
header={
"Cookie":";".join([f"{cookie['name']}={cookie['value']}" for cookie in cookies]),
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36",
"X-Requested-With":"XMLHttpRequest"}
params={
"page":1, # 第n页,从1开始
"pageSize":30 # 每页数据量
}
resp=requests.get(lib_url,params=params,headers=header).json()
return resp
print(get_libs())
网友评论