$.post请求的参数在后台代码中得到为null_996难得休息,小伙打开steam网页看了一款游戏,输入密码后却习惯性按了F12研究起了JS代码...
登录后才能获取数据也是现在反爬的一个重点,本期我们来看看两种登录方式,分别参考豆瓣与steam,由于js代码过长,所以只截取了部分,完整代码移步
从今天开始种树www.happyhong.cn
,直接拷贝运行即可,老铁们可别忘了点个点阅啊。
啰嗦两句
各大网站登录提交数据的方式不太 一样,有些只需要POST
明文的账号密码、有些网站POST
的密码是经过加密的(RSA、BASE64、AES、SHA1
等等),还有些网站增加了一些其它的参数,而这些网站的统一特点就是均可以从JS文件
中提取加密代码复现出来,获得这些代码则完全依靠数据提取师父们个人的调试能力了,下面就尝试去登录两个不同的网站-豆瓣与Steam
。
明文提交
明文提交最典型的就是豆瓣,输入错误密码按F12
然后点击登录发现,提交的url为https://accounts.douban.com/j/mobile/login/basic
,提交的数据只有username和password
,还有其它两个空的参数:
这种登录方式属于Baby级的,甚至于都不需要写一个登录类或者函数,不过有点需要注意的是你需要带着cookie去post账号密码,如果你代码中直接POST
到这个url是不会成功的,除非你在请求头中添加了cookies
,还有一种办法就是先用requests.Session
, session方式请求豆瓣的网址,下一次请求就会自动带上cookie,代码如下:
import requests
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36",
}
url = "https://www.douban.com/"
session = requests.Session()
session.get(url,headers=headers, verify=False)
login_url = "https://accounts.douban.com/j/mobile/login/basic"
login_data = {"ck": "","name": "nide","password": "nide","remember": "false","ticket": "",
}
resp = session.post(login_url, data=login_data, headers=headers, verify=False)
print(resp.text)
登录成功:
加密登录
前言
Steam作为全球最大的一个男性购物平台,每天都有可能捡漏到一些折扣较低的游戏。假设你有代码在监控平台上的游戏折扣,在购买时当然需要先登录,要实现自动化的过程,首先就得让你的账号自动登录,接下来就看看如何实现Steam登录(如需监控游戏商城需自行发挥,本文不涉及相关内容)。
分析
关于如何打开Steam登录网页之类的就不废话了,直入正题,Steam登录url为https://store.steampowered.com/login/?redir=&redir_ssl=1
,请求这个url就会到账号密码输入环节,老方法按F12
,先看看输入错误账号密码时候返回的内容,比如我输入的是账号为test
,密码为123456
:
点击登录,查看网络请求发现有两个,getrsakey
和dologin
:
首先看一下getrsakey/
请求,通过上图可以看到请求url为https://store.steampowered.com/login/getrsakey/
,方法为POST
,提交的参数如下:
donotcache
看着像是时间戳,username
就不用说了,点击Preview
看看返回了什么内容:
返回了一些参数,但是现在还不知道这些有何用处,接着查看dologin/
:
提交的路径为https://store.steampowered.com/login/dologin/
,POST
的参数为:
基本可以断定donotcache
是时间戳了,而password
则经过了各种加密,关于rsatimestamp
如果观察仔细的话可以看到其值与getrsakey/
返回的timestamp
的值是一样的,其它几个参数基本可以忽略了:
经过分析,现在需要获取的值就只有经过加密的password
,那就去Sources
里搜索一下看看有没有包含passwor
的js文件,查找结果如下:
有几个js文件都包含了password
变量,但是结果观察发现login.js
文件中包含了很多password
,甚至都能看到RSA.encrypt
的字样,那基本就确定了我们想要的加密过程就在这个文件里,那就打开这个文件看看吧:
上面红框里的内容已经很明了了,加密的函数在RSA.encrypt
里,这个函数有两个参数:password
和pubkey
,pubkey
是通过RSA.getPublickey
函数得到的,这个函数也有两个参数:result.publickey_mod
和result.publickey_exp
,看着似曾相识,其实倒回去到https://store.steampowered.com/login/getrsakey/
链接返回的地方可以看到有两个同名的参数返回,这里再贴一次,但是现在还不能确定是不是,还需要再调试:
调试
在387
处打一个断点开始调试:
这里可以看到result.publickey_exp
为010001
与前面返回的publickey_exp
一样,result.publickey_mod
也一样,下面是getPublickey
函数,这是已经跳转到另外一个名为rsa.js
的JS文件里,:
RSA.encrypt
同样也在这个文件里,可以看出encrypt
里还包含Base64
加密:
Bases64
:
继续运行,直到加密完返回到login.js
中:
到这里其实整个流程都理清楚了,主要就是获取pubkey
,然后再通过pubkey
去加密password
,这里我把rsa.js
文件复制了下来,再加上login.js
中对password
的一些处理操作,重新整合了一个js文件。有能力的童靴可以用python去复现一下,水平有限,我就直接用的execjs
库去执行了,execjs
库的安装参考我上一篇。
部分JS代码
篇幅有限,只展示部分js代码了,完整代码移步从今天开始种树:
navigator = {};
var dbits;// JavaScript engine analysis
var canary = 0xdeadbeefcafe;
var j_lm = ((canary&0xffffff)==0xefcafe);// (public) Constructor
function BigInteger(a,b,c) {if(a != null)if("number" == typeof a) this.fromNumber(a,b,c);else if(b == null && "string" != typeof a) this.fromString(a,256);else this.fromString(a,b);
}// return new, unset BigInteger
function nbi() { return new BigInteger(null); }
function am1(i,x,w,j,c,n) {while(--n >= 0) {var v = x*this[i++]+w[j]+c;c = Math.floor(v/0x4000000);w[j++] = v&0x3ffffff;}return c;
}function am2(i,x,w,j,c,n) {var xl = x&0x7fff, xh = x>>15;while(--n >= 0) {var l = this[i]&0x7fff;var h = this[i++]>>15;var m = xh*l+h*xl;l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);w[j++] = l&0x3fffffff;}return c;
}
....
省略
.....var RSA = {getPublicKey: function( $modulus_hex, $exponent_hex ) {return new RSAPublicKey( $modulus_hex, $exponent_hex );},encrypt: function($data, $pubkey) {if (!$pubkey) return false;$data = this.pkcs1pad2($data,($pubkey.modulus.bitLength()+7)>>3);if(!$data) return false;$data = $data.modPowInt($pubkey.encryptionExponent, $pubkey.modulus);if(!$data) return false;$data = $data.toString(16);if(($data.length & 1) == 1)$data = "0" + $data;return Base64.encode(Hex.decode($data));},pkcs1pad2: function($data, $keysize) {if($keysize < $data.length + 11)return null;var $buffer = [];var $i = $data.length - 1;while($i >= 0 && $keysize > 0)$buffer[--$keysize] = $data.charCodeAt($i--);$buffer[--$keysize] = 0;while($keysize > 2)$buffer[--$keysize] = Math.floor(Math.random()*254) + 1;$buffer[--$keysize] = 2;$buffer[--$keysize] = 0;return new BigInteger($buffer);}
};
function pwd(password,publickey_mod,publickey_exp) {password = password.replace(/[^x00-x7F]/g, '');console.log(publickey_mod)console.log(publickey_exp)var pubKey = RSA.getPublicKey(publickey_mod,publickey_exp)var encryptedPassword = RSA.encrypt(password, pubKey);return encryptedPassword
}
python代码
Steam
类继承自自己写的SpiderBase
类,有兴趣完整复制的请移步
SpiderBase类www.happyhong.cn
import json
import time
from spider.spider_base import SpiderBase
import requests
requests.packages.urllib3.disable_warnings()
class Steam(SpiderBase):def __init__(self):super().__init__()self.rsa_url = "https://store.steampowered.com/login/getrsakey/"self.login_url = "https://store.steampowered.com/login/dologin/"self.js_path = '..//js//steam.js'self.username = "你的"self.password = "你的"self.ua = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36"}def login(self):resp = self.get_rsa()rsakey = json.loads(resp.text)print(rsakey)js = self.exec_js(self.js_path)enc_password = js.call('pwd', self.password, rsakey["publickey_mod"], rsakey["publickey_exp"])print(enc_password)login_data = {'donotcache': int(time.time() * 1000),'password': enc_password,'username': self.username,'twofactorcode': '','emailauth': '','loginfriendlyname': '','captchagid': '-1','captcha_text': '','emailsteamid': '','rsatimestamp': rsakey['timestamp'],'remember_login': 'false',}resp = self.session.post(self.login_url,data=login_data,headers = self.ua,verify=False)print(resp.text)def get_rsa(self):rsakey_data = {'donotcache': int(time.time()*1000),'username': self.username}resp = self.session.post(self.rsa_url,data=rsakey_data,headers=self.ua,verify=False)return respif __name__ == '__main__':st = Steam()st.login()
运行
success
为true
即代表登录成功,接下来你可以进行你的操作了。
结束语
到这里就结束了,为了节省篇幅,完整代码发布在个人博客网站从今天开始种树,有兴趣的可以直接复制运行。
更多内容请移步从今天开始种树,关注知识图谱与大数据公众号,获取更多内容,当然不关注也无所谓。
最新文章
- P vs. NP 五十年:AI正在解决不可解问题
- python 输出“Hello, world”
- YOLO学习-1:win10(64位)+ python3.6 + TensorFlow + keras + yolov3测试实践
- struct结构体和char型数组的相互转化
- MySQL优化(四):count()
- C++之带有默认参数值的构造函数
- 吴恩达机器学习笔记一
- Elasticsearch 8.x 正式发布!
- Unite'17 Shanghai再一次问候
- U盘刻录方式安装CentOS 7
- Springboot+ssm高校会议预约系统javaweb
- 破解Bandicam
- rtthread iic读取M24C64的测试程序
- 华为携手Work Shift Calendar (Shifter),将工作效率提升至更高水平
- 【Oracle SQL】计算同比与环比(列转行进行偏移)
- WIN11电脑如何使用IE浏览器进行正常办公操作-以建行网银为例
- 阿里巴巴初创时的十八罗汉,离开阿里之后都有什么故事?
- 第三方登录/分享最佳实践
- python 机器视觉测量_用Opencv python实现精密测量
- 移动端框架之mand-mobile
热门文章
- jquery封装的ajax请求
- What are HANA's models of cloud computing, and which should I choose?
- PMBOK学习笔记二-项目管理过程
- windows下常用命令
- maven 与intellij IDEA 下maven 为groovy 项目生成jar 详解
- Struts2 method=get方法乱码
- golang 正则表达式 简介
- golang编译错误 copying /tmp/go-build069786374/b001/exe/a.out: No such file or directory 解决方法
- couchdb 任意命令执行漏洞 cve-2017-12636
- 操作系统识别工具 xprobe2 p0f 简介