Python 爬虫反爬突破:Cookie 加密生成算法逆向还原登录凭证
前言现代大中型互联网平台的用户登录环节已摒弃明文 Cookie 下发模式多数后端依托自定义哈希、对称 / 非对称加密、时间戳加盐、动态密钥衍生等逻辑生成加密 Cookie 与登录凭证常规抓包复制 Cookie、固定账号密码表单提交的爬虫方案会在短周期内失效平台通过校验 Cookie 加密签名、时效字段完成爬虫访问拦截。针对加密 Cookie 逆向还原可通过 JS 源码剥离加密逻辑、还原密钥与盐值、复刻客户端加密算法由爬虫程序自主生成合法登录 Cookie摆脱手动获取登录凭证的依赖实现全自动持久化账号登录采集。 本文所需依赖库官方访问链接统一置于开篇便于开发阶段查阅文档与安装配置requests HTTP 请求库pycryptodome 加解密工具库execjs JS 引擎调用库hashlib Python 内置哈希库json 内置序列化库全文从 Cookie 加密常见实现分类、前端 JS 逆向步骤、三种主流加密算法 Python 复刻、动态凭证生成实战、异常校验绕过、登录态持久化存储六大板块展开搭配全量可运行工程代码覆盖 MD5 加盐、AES 对称加密、RSA 非对称加密三类登录 Cookie 主流加密场景落地爬虫全自动生成合法登录凭证的工程方案。一、登录 Cookie 加密分类与反爬校验原理1.1 平台登录 Cookie 主流加密类型划分从前端逆向落地角度网站登录凭证加密分为哈希加盐、对称加密、非对称加密三类各类加密特征与应用场景整理如下表表格加密类型核心实现特征Cookie 字段特征平台使用场景加盐哈希加密基于 MD5/SHA1/SHA256 固定 / 动态盐值拼接摘要sign、token 字段为固定长度十六进制字符串中小型资讯、电商后台简易登录校验AES 对称加密固定密钥 偏移量明文账号信息加密生成密文密文长度不固定含大小写字母与数字混合串中大型会员系统、移动端 H5 登录鉴权RSA 非对称加密前端公钥加密关键参数后端私钥解密校验密文字符长度偏大无固定规律银行、票务、大型电商核心账号登录1.2 加密 Cookie 反爬拦截底层逻辑客户端登录请求携带账号、密码、时间戳、随机数经前端加密生成签名字段后端使用同源加密规则与密钥复算签名对比请求携带的 sign 值不一致直接返回登录失败登录成功下发加密 CookieCookie 内嵌时效戳、设备标识加密字段每次接口请求后端二次解密校验有效性爬虫直接复用过期 Cookie、手动篡改 Cookie 参数会触发会话失效、IP 风控拦截。1.3 逆向还原 Cookie 核心思路定位页面登录相关 JS 文件剥离加密函数、密钥、固定盐值区分加密类型使用 Python 复刻同等加密逻辑保证输出密文与浏览器 JS 运算结果完全一致爬虫自主组装明文参数通过自研加密函数生成合法签名提交登录接口获取新鲜登录 Cookie缓存有效 Cookie临近过期自动重新执行加密登录实现全自动化凭证轮换。二、项目环境与依赖安装2.1 运行环境基准配置Python3.8 及以上Node.js 环境execjs 运行原生 JS 代码必备用于临时调试 JS 加密逻辑Windows/Linux 全平台兼容。2.2 第三方依赖一键安装指令bash运行pip install requests pycryptodome execjs2.3 依赖有效性校验代码python运行import requests import execjs from Crypto.Cipher import AES, PKCS1_OAEP print(加解密相关依赖加载正常)三、场景一MD5 加盐哈希加密 Cookie 逆向复刻3.1 加密原理说明平台前端将账号密码时间戳固定盐值secret_key拼接为原始明文经 MD5 哈希运算生成 sign 签名字段随登录表单一并提交后端使用相同盐值复算 MD5 完成校验登录成功返回携带加密 sign 的会话 Cookie。盐值硬编码在前端 JS 源码内逆向目标即为提取 secret_key 与字段拼接顺序。3.2 JS 源码逆向提取示例模拟前端加密代码javascript运行// 从网站js文件剥离的原始加密逻辑 var secret k9s20df37gglp0x; //逆向得到固定盐值 function getSign(username,pwd,ts){ var raw username pwd ts secret; return md5(raw); }3.3 Python 复刻加密函数与完整登录爬虫代码python运行import hashlib import requests import time class MD5SignLoginCrawler: def __init__(self): # 逆向JS获取固定盐值 self.secret_key k9s20df37gglp0x self.login_url https://target.com/api/login self.session requests.Session() self.headers { User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } def calc_md5_sign(self,user,pwd,ts): 复刻前端MD5加盐签名算法 raw_str user pwd str(ts) self.secret_key md5_res hashlib.md5(raw_str.encode(utf-8)).hexdigest() return md5_res def auto_login(self,username,password): 自主生成签名提交登录获取加密Cookie ts int(time.time()) sign self.calc_md5_sign(username,password,ts) post_data { username:username, password:password, timestamp:ts, sign:sign } resp self.session.post(self.login_url,datapost_data,headersself.headers,timeout8) if resp.status_code 200 and resp.json().get(code) 200: print(登录成功已自动保存加密登录Cookie至session) cookie_dict self.session.cookies.get_dict() print(当前有效登录Cookie,cookie_dict) return True else: print(登录失败签名或参数异常) return False if __name__ __main__: craw MD5SignLoginCrawler() craw.auto_login(test_account,123456abc)3.4 代码原理拆解严格沿用逆向所得盐值与字符串拼接顺序字符编码统一 utf-8保证 MD5 结果与前端 JS 完全匹配使用 requests.Session 自动托管登录下发的加密 Cookie后续业务请求直接复用会话实例时间戳实时生成规避固定时间戳导致的签名过期失效问题。四、场景二AES 对称加密登录 Cookie 逆向实现4.1 AES 加密逻辑说明前端采用 AES-CBC 加密模式固定 16 位密钥 key 与 16 位偏移向量 iv账号、密码明文经 AES 加密后作为请求参数后端使用同源 key 与 iv 解密校验账号合法性后下发加密 Cookie。逆向重点从 JS 中提取 key、iv、填充规则、编码格式。4.2 前端 JS 加密源码逆向提取javascript运行//逆向获取AES配置参数 var aes_key 16bitskey0000000; var aes_iv iv16bit00000000; function aesEncrypt(rawText){ //CBC模式、pkcs7填充、base64输出密文 }4.3 Python AES 加密复刻与登录实现python运行from Crypto.Cipher import AES from Crypto.Util.Padding import pad import base64 import requests class AESLoginCrawler: def __init__(self): self.key b16bitskey0000000 self.iv biv16bit00000000 self.login_api https://target.com/aes/login self.sess requests.Session() def aes_cbc_encrypt(self,raw_text): 复刻前端AES-CBC加密逻辑 cipher AES.new(self.key,AES.MODE_CBC,self.iv) raw_byte raw_text.encode(utf-8) padded_data pad(raw_byte,AES.block_size) encrypt_data cipher.encrypt(padded_data) cipher_base64 base64.b64encode(encrypt_data).decode(utf-8) return cipher_base64 def login_by_aes(self,user,pwd): enc_user self.aes_cbc_encrypt(user) enc_pwd self.aes_cbc_encrypt(pwd) payload {username:enc_user,password:enc_pwd} res self.sess.post(self.login_api,jsonpayload,timeout7) if res.json().get(success): print(AES加密登录成功会话Cookie已自动保存) return self.sess.cookies print(AES加密登录失败) return None if __name__ __main__: obj AESLoginCrawler() obj.login_by_aes(spideruser,pass123654)4.4 关键实现要点AES-CBC 要求密钥、偏移向量长度必须为 16 字节和前端 JS 配置保持一致采用 pkcs7 填充对齐分组长度密文 base64 编码后传输和前端输出格式统一加密参数错误会直接触发后端解密异常返回登录拒绝逆向时不可随意修改 key 与 iv。五、场景三RSA 非对称加密登录凭证逆向5.1 RSA 加密业务逻辑前端使用平台公钥对明文密码加密后端持私钥解密校验密码公钥明文暴露在前端 JS 中爬虫逆向提取公钥即可自主完成密码加密提交登录获取 Cookie。RSA 特征公钥加密、私钥解密私钥仅存放后端无法逆向获取。5.2 Python RSA 加密实现代码python运行from Crypto.Cipher import PKCS1_OAEP from Crypto.PublicKey import RSA import base64 import requests class RSALoginCrawler: def __init__(self): # 逆向前端提取RSA公钥字符串 self.pub_key_str -----BEGIN RSA PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCFENGw33yGihy92pDjZQhl0C3 6PJrlrvfSKQjXifSx1WuuFjpxX5u3vYjBqbD1dA2YcCotbl959aksgn3jR38W9D RQLafY2kXAKvNOC1RXZZbOFKAypDvt1FmnL4R593D45oq5Mj5pqGzcUELRmlpb4 xy3szGCOUDfaDufIYfwIDAQAB -----END RSA PUBLIC KEY----- self.login_url https://target.com/rsa/login self.session requests.Session() def rsa_pwd_encrypt(self,raw_pwd): pub_key RSA.import_key(self.pub_key_str) cipher PKCS1_OAEP.new(pub_key) enc_byte cipher.encrypt(raw_pwd.encode(utf-8)) return base64.b64encode(enc_byte).decode() def auto_rsa_login(self,account,pwd): enc_pwd self.rsa_pwd_encrypt(pwd) data {user:account,password:enc_pwd} resp self.session.post(self.login_url,datadata) if resp.json()[code] 1: print(RSA加密登录完成成功获取加密登录Cookie) return self.session.cookies return None if __name__ __main__: rsa_crawl RSALoginCrawler() rsa_crawl.auto_rsa(testacc,mima123)六、execjs 直跑前端 JS免复刻快速生成 Cookie部分站点加密逻辑冗长、多层函数嵌套手动复刻成本偏高可直接提取完整加密 JS 代码通过 execjs 在 Python 环境调用原生 JS 运算1:1 还原浏览器加密结果。python运行import execjs import requests # 逆向扒取完整加密JS源码 js_code function getSign(name,pw,t){ var s k9s20df37gglp0x; function md5(s){/*省略前端md5实现代码*/} return md5(namepwts); } class JsDirectLogin: def __init__(self): self.ctx execjs.compile(js_code) self.sess requests.Session() self.login_api https://xxx.com/login def get_js_sign(self,user,pwd,ts): return self.ctx.call(getSign,user,pwd,ts) def login(self,usr,pwd): import time ts int(time.time()) sign self.get_js_sign(usr,pwd,ts) res self.sess.post(self.login_api,data{u:usr,p:pwd,t:ts,sign:sign}) print(JS原生加密登录Cookie,self.sess.cookies) if __name__ __main__: jscrawl JsDirectLogin() jscrawl.login(user01,pass654)实现优势无需逐行翻译加密算法规避 Python 与 JS 数据类型差异带来的加密结果不一致问题适合复杂混淆 JS 加密场景。七、登录 Cookie 持久化存储与过期自动续登加密生成的登录 Cookie 存在有效期通过 JSON 文件 / Redis 持久化存储 Cookie每次请求前校验有效性失效自动调用加密登录函数刷新凭证。python运行import json import os def save_cookie(cookie_dict,file_pathlogin_cookie.json): with open(file_path,w,encodingutf-8) as f: json.dump(cookie_dict,f,ensure_asciiFalse) def load_cookie(file_pathlogin_cookie.json): if not os.path.exists(file_path): return None with open(file_path,r,encodingutf-8) as f: return json.load(f)业务调用逻辑加载本地 Cookie访问测试接口返回未登录状态则重新加密登录生成新 Cookie 并覆盖保存。八、逆向常见坑点与故障处理方案表格故障现象问题成因解决方案Python 加密密文和前端不一致字符编码、填充规则、盐值提取错误逐行比对 JS 拼接顺序统一 utf-8 编码核对 AES 填充方式RSA 加密报错超长RSA 单次加密明文长度受限拆分密码分段加密或改用前端约定分段规则生成签名正确依旧登录失败存在 UA、设备指纹隐藏校验同步浏览器 UA补齐 header 内隐性设备参数Cookie 短期内失效内嵌时效加密字段每次请求动态刷新封装拦截接口自动抓取新下发 Cookie 并落地存储