js调试(九)

通过微博登录案例来进行了解js调试

1.分析流程

(1)手动操作流程

  1. 访问首页https://weibo.com
  2. 输入用户名和密码
  3. 点击登录
  4. 如果有验证码,就输入验证码验证
  5. 成功跳转到微博首页面

(2)微博首页请求流程分析过程

根据上面的手动操作流程,我们要分析出网站的http请求逻辑。

1.首页面请求分析

首先,打开谷歌浏览器开发者调试工具,查看在请求首页面时,请求回的响应是否包含cookie,也即是看首页面的响应头中是否包含set-cookie。如果包含,那么这个请求是登录过程中必须的。经过查看,发现在首页面的响应头中,包含set-cookie,这个请求是登录的第一个请求。

注意:Network选项是监控页面的请求信息
根据经验,在请求页面的html之后,还会去请求页面中的jscss,图片等信息。css,图片信息我们可以排除,一般情况,不会是登录的必须请求。一种常见的手法是,将后续请求需要用到的参数放到js中,然后通过js异步请求来完成登录。所以,我们在Network中过滤出所有的js请求。然后一个请求一个请求的查看,查看请求返回的响应内容,排除一些功能性的js,例如jquery之类,找出可能是参数的js,一般你能看懂的,大概率是参数。没有特别有效的方法,只能一条一条的看,凭借经验,以及url的命名。果然,找到了一条可疑请求,url为:https://login.sina.com.cn/sso/prelogin.php
这是一条jsonp的请求,其中包含了几个关键参数pubkey,noncersakv,这是rsa加密用的参数,在后面的请求中一定会用到。分析请求参数,发现除了最后有个时间戳解决浏览器缓存之外,其他参数都是固定的。
除了查看js请求外,还应该,查看ajax请求,调试工具里,也可以过滤出,选择XHR过滤选项。
经过判断,这两个请求是必要请求的可能性不大。
根据流程,可以先实现代码此部分的代码。

import requests
import time
import re
import json

#创建一个浏览器对象
session = requests.session()
#将浏览器对象进行伪装
session.headers.update({'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'})
#请求首页面,获取cookie(看浏览器里面是否存在cookie值 )
response = session.get('https://weibo.com/')
# print(response.cookies)
# print(session.cookies)

#请求prelogin,获取响应内容
params = {'entry': 'weibo',
        'callback': 'sinaSSOController.preloginCallBack',
        'su':'',
        'rsakt': 'mod',
        'client': 'ssologin.js(v1.4.19)',
          '_': int(time.time())}
rs = session.get('https://login.sina.com.cn/sso/prelogin.php', params=params)
#print(rs.text)
data = re.findall(r'\((.*?)\)', rs.text)[0]
data = json.loads(data)
print(data, type(data))

2.点击登录后请求的分析

先清空调试工具中的请求历史,然后勾选Preserver logDisable cache,保证抓包的正确。

点击登录,根据请求url,以及响应头中是否有有设置cookie,找到第一个设置cookie的请求。请求url为:https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19)
分析其请求参数。
可以发送多次请求,然后比较参数,筛选出固定参数。然后去分析非固定参数。

上图红框中是几个比较关键的参数,在其中,没有发现usernamepassword的字样,但是nonce,pwencode,rsakv,以及sp的值都明确指明了参数被js加密了。需要分析页面js,最笨的办法是在查找此条请求之前的所有请求中的js,然后找到处理参数的js。有时候,笨办法是最好的办法。谷歌浏览器提供的开发者调试工具中有个js调试工具,它可以定位页面元组的js事件,然后通过断点的方式,一步一步定位到关键代码处。

退回到点击登录按钮的那一步。点击开发者工具Elements选项卡,点击左上角的选中按钮,然后用鼠标左定位页面中的登录按钮。

再点击开发工具窗口中的右边的子窗口,选中Events Listeners, 找到click事件,从而定位到js代码。
然后再点击,右边的js代码,会打开调试工具的sources窗口,它由3个子窗口组成,从左往右依次为,文件目录窗口js代码窗口调试窗口。大多数情况,为了减少带宽的消耗,js会被压缩,点击代码窗口左下角的{}可以格式化js。
点击格式化后,js代码会自动跳到上面click监听时间执行的入口函数处,它会高亮黄色显示。在对于的行号出用鼠标左键点击,给当前代码处打上断点,行号显示为蓝色箭头,代表打上了断点。
打好断点后,就可以开始调试了,点击登录按钮,js会暂停到刚才断点处,然后使用调试工具,一步一步进行调试,分析js代码,直到找到关键代码。
对于微博登录的案例来说,通过着这种调试方法定位关键代码非常困难,因为代码调用层级太多。有些时候,必须一步一步调试,知道找到关键代码,js调试需要极有耐心。

但是,有一种情况,可以换另外一种方法定位。那就是如果你要找某个请求的触发函数,那么可以直接在networking选项窗口直接定位。输入错误密码,然后点击登录,请求的Initiator字段显示了,发送这条请求的发起对象。

点击发起对象字段的js文件名,会跳到发起请求的js处。打上断点,然后进行调试。
当前这个函数e.submit是发起http请求的函数,这不是分析目标,分析的目标是请求参数的构造。查看当前函数loginByIframe,发现没有参数构造的步骤。通过函数栈图,找到调用这个函数的函数loginByConfig,在栈图中点击这个函数,可以跳到loginByIframe函数调用处,在此处打上断点。
分析js代码,发现登录函数login在196行,打上断点,然后刷新页面,再次点击登录。一步一步开始分析
调试模式,会实时显示函数中的变量的值,也可以在右边的Scope选项中查看当前变量。
函数login的,形参a是用户名,形参b是密码。经过分析找到如下代码
发现用户名处理为参数su,处理方式为,先urlencodebase64encode。继续往下调试
可以看出urlencode就是对用户名进行url编码,python中使用如下代码

import base64
from urllib import parse

username = '112064149@qq.com'
res = parse.quote(username)
print(res)
# 输出:
112064149%40qq.com

继续调试,得到username编码后的值

通过python代码实现如下:

import base64
from urllib import parse

username = '112064149@qq.com'
res = parse.quote(username)

res = base64.b64encode(res.encode())
print(res.decode('utf-8'))
# 输出
MTEyMDY0MTQ5JTQwcXEuY29t

仔细观察代码,发现参数entry,service,nonce,pwencode,rsakv,以及密码sp和它的加密方式。


继续按照这样的分析方式可以找到所有剩余参数的构造方法。

继续上面的python代码,实现这一步操作。

# 2.提交登录请求


def get_username(username):
    res = parse.quote(username)

    res = base64.b64encode(res.encode())
    return res.decode('utf-8')


def get_password(pubkey, password):
    # publickey = rsa.PublicKey(int(pubkey, 16), int('10001', 16))
    # res = rsa.encrypt(password.encode(), publickey)
    rsa = Rsa(pubkey=pubkey)
    res = rsa.encrypt(password.encode())
    return binascii.b2a_hex(res).decode()


t2 = str(int(time.time()*1000))


form_data = {
    'entry': 'weibo',
    'gateway': '1',
    'from': '',
    'savestate': '7',
    'qrcode_flag': 'false',
    'useticket': '1',
    'pagerefer': '',
    'vsnf': 1,
    'su': get_username('122064149@qq.com'),
    'service': 'miniblog',
    'servertime': data['servertime'],
    'nonce': data['nonce'],
    'pwencode': 'rsa2',
    'rsakv': data['rsakv'],
    'sp': get_password(data['pubkey'], str(data['servertime']) + '\t' + data['nonce']+'\n'+'pythonvip123'),
    'sr': '1920*1080',
    'encoding': 'UTF-8',
    'prelt': '49',
    'url': 'https://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack',
    'returntype': 'META'
}

login_url = 'https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19)'
res = session.post(url=login_url, data=form_data)

res.encoding = 'gbk'
print(res.text)

运行结果:

返回的结果是一个html页面,结构比较简单,js代码中有一个location.replace的跳转语句,说明接下来浏览器会发送这个请求。通过正则表达式提取url,然后发送请求。

next_url = re.findall(r'replace\("(.*?)"\)', res.text)[0]
# print(parse.unquote(next_url, encoding='gbk'))

response = session.get(next_url)
response.encoding = 'gbk'

print(response.text)

运行结果:


仍然是一个html页面,分析其中的js,发现一个arrURL的列表,观察其中的url,对照浏览器抓包,发现都有请求,通过代码提取,然后依次请求。最后访问home页面https://weibo.com/?wvr=5&lf=reg。调试后发现,arrURL中除了第一个请求必须之外,其他的请求都可以不发送。到此微博登录成功实现。

response = session.get(next_url)
response.encoding = 'gbk'

arrurl = re.findall(r'setCrossDomainUrlList\((.*?)\)', response.text)[0]
arrurl = json.loads(arrurl)['arrURL']

res = session.get(arrurl[0])
res.encoding = 'gbk'
print(res.text)
# res = session.get(arrurl[1])
# res.encoding = 'gbk'
# print(res.text)
# res = session.get(arrurl[2])
# res.encoding = 'gbk'
# print(res.text)
# res = session.get(arrurl[3])
# res.encoding = 'gbk'
# print(res.text)
res = session.get('https://weibo.com/?wvr=5&lf=reg')
print(res.url)
print(res.text)
import requests
import time
import re
import json
from urllib import parse
import base64
from Cryptodome.Cipher import PKCS1_OAEP, PKCS1_v1_5 #用的是比较老的模式PKCS1_v1_5
from Cryptodome.PublicKey import RSA
import binascii


def encrypt_username(username):
    temp = parse.quote(username)
    res = base64.b64encode(temp.encode())
    return res.decode('utf-8')


# print(encrypt_username('wswdd'))
# if encrypt_username('wswdd') == 'd3N3ZGQ=':
#     print('是相等的')


def encrypt_password(password, pubkey):
    public_key = RSA.RsaKey(n=int(pubkey, 16), e=65537)
    cipher = PKCS1_v1_5.new(public_key)
    res = cipher.encrypt(password.encode())
    return binascii.b2a_hex(res).decode()

#创建一个浏览器对象
session = requests.session()
#将浏览器对象进行伪装
session.headers.update({'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'})
#请求首页面,获取cookie(看浏览器里面是否存在cookie值 )
response = session.get('https://weibo.com/')
# print(response.cookies)
# print(session.cookies)

#请求prelogin,获取响应内容
params = {'entry': 'weibo',
        'callback': 'sinaSSOController.preloginCallBack',
        'su':'',
        'rsakt': 'mod',
        'client': 'ssologin.js(v1.4.19)',
          '_': int(time.time())}
rs = session.get('https://login.sina.com.cn/sso/prelogin.php', params=params)
#print(rs.text)
data = re.findall(r'\((.*?)\)', rs.text)[0]
data = json.loads(data)
# print(data, type(data))
# print('-'*100)

#发送用户名和密码(在谷歌中有一个door参数,是要验证码的)
login_data = {
        'entry': 'weibo',
        'gateway': 1,
        'from': '',
        'savestate': '7',
        'qrcode_flag': 'false',
        'useticket': '1',
        'pagerefer': '',
        'pcid': 'yf-a9af4495ac9f6a582caeb643033d45f3725e',
        'vsnf': '1',
        'su': encrypt_username('15115203567'),
        'service': 'miniblog',
        'servertime': data['servertime'],
        'nonce': data['nonce'],
        'pwencode': 'rsa2',
        'rsakv': data['rsakv'],
        'sp': encrypt_password(str(data['servertime'])+"\t" + data['nonce'] + "\n" + 'qwer4321', data['pubkey']),
        'sr': '1366*768',
        'encoding': 'UTF-8',
        'prelt': '391',
        'url': 'https://www.weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack',
        'returntype': 'META',}
# print(login_data)
response = session.post('https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19)', data=login_data)
response.encoding = 'gbk'
# print(response.text)
# print('--'*100)
redirect_url = re.findall(r'replace\("(.*?)"\)', response.text)[0]
# print(redirect_url, type(redirect_url))
# print('--'*100)
# print(parse.unquote(redirect_url, encoding='gbk'))
response = session.get(redirect_url)
response.encoding = 'gbk'
# print(response.text)
# print('-'*100)


#获取url列表
urls = re.findall(r'"arrURL":(\[.*?\])', response.text)[0]
# print(urls, type(urls))
urls = json.loads(urls)
# print('-'*100)
print(urls, type(urls))

for res in urls:
    response = session.get(res) #只取第一个即可
    print(response.text)
    print('='*100)
print('='*100)
response = session.get('https://weibo.com/?wvr=5&lf=reg')
response.encoding = 'utf-8'
print(response.text)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351