Chinaunix首页 | 论坛 | 博客
  • 博客访问: 99369
  • 博文数量: 41
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 0
  • 用 户 组: 普通用户
  • 注册时间: 2018-05-23 12:43
文章分类

全部博文(41)

文章存档

2016年(2)

2015年(3)

2014年(16)

2013年(20)

分类: Java

2013-09-14 13:59:37

原文链接:
概述:

 

由于业务需要,要编写爬虫代码去爬去新浪微博用户的信息。

虽然在网上能找到不少信息,但由于新浪微博改版,其登陆机制进行了修改,故很多老的文章就不适合用了。

经过一番摸索,成功模拟新浪微博的登陆操作,项目使用的是Javascript语言,在ChromeExtension中运行, 跟大家分享一下这一过程和心得。

 

注意,本文写于2013.08.16,由于微博业务经常变化,随年月老去,文章可能不再适用。 

 

 

 正文:探索的过程

 

1. 了解大致过程

 

登陆微博,使用fiddler工具监视HTTP请求,截获如下操作:

 

可以看到在微博登陆的整个过程中,有四次重要的HTTP请求,分别是:

(1) GET /sso/prelogin.php

(2) POST /sso/login.php 

(3) GET /ajaxlogin.php

(4) GET /u/2813262187 

 

其中,sso是single sign on

(1) 是登陆前的预处理,名字也显而易见--pre,这一步操作主要是拿到了几个重要的参数,用作下一步POST表单的参数。

可以在浏览器中访问这一请求的地址,查看返回的结果:

(v1.4.11)

结果如下:

1 sinaSSOController.preloginCallBack({"retcode":0,
2 "servertime":1376533839,
3 "pcid":"gz-7bdd82b8980057a8bbc1f86b21d5a86184dd",
4 "nonce":"R1KGHZ",
5 "pubkey":"EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443",
6 "rsakv":"1330428213",
7 "exectime":2})

 

返回的数据有servertime:服务时间戳,nonce:是一个6位随机码,pubkey:是用于rsa2密码加密的公钥,rsakv:显然也是加密用的。

这四个值都是需要在下一步用到的。

 

在久版本的新浪微博登陆机制当中,使用的是sha的加密方式,没有pubkey和rsakv参数,

因此,在网上看到的2012年的爬虫代码模拟登陆的代码都已经不适合用,但总体逻辑是没多大变化的,只需要稍作修改还是能用的,我就是这么走过来的,碰壁无数=.= 

给出两篇参考文章:

For Python 

For PHP

 

(2) 提交表单的操作,我们依然是查看HTTP请求,看表单内容

 

 

看到了,servertime、nonce、rsakv,还有su:加密后的用户名,sp:加密后的密码。现在问题就是用户名跟密码是怎么加密的了,很容易地我们的目光聚焦到js代码上面

  请求新浪登陆页面:,里面有用于密码加密的js代码,

里面的代码是加密过的,找个工具解密一下(), 勉强还能看到其中的逻辑的。

 

(3) 分析ssologin.js 

  既然我们知道了servertime跟nonce是用于加密的,不妨在文件中搜一下这两个关键字,一搜找到了好东西:

 

 

翻回去上文看看,表单中有个su和sp,都在这里了,可以看到su使用的是base64加密方式;而su就稍微复杂一点了,

if中的是新浪当前版本的密码加密方式rsa2的代码,而else中的是就版本sha加密的代码,我们只需要关心if中的内容, 

加密过程很简单,先是生成一个RSAKey对象, set PublicKey,然后就加密了。

一项一项地倒推回去,可以知道最后一步加密中最后的一个参数ag是原始的密码值,不会看到眼花的~ 

 

概括一下,就是用好长的那一串pubkey和10001作参数调用setPublic() ,注意的是它们都十六进制数;然后用(servertime + nonce + pwd)作参数调用Encrypt()。

 

我们去看看sinaSSOEncoder是个什么东西,它的定义在解密了的代码的1118行,从这开始截取到文件末尾,挪出来我们自己用,

 

1 }).call(sinaSSOEncoder);
2 //sinaSSOController = new SSOController();
3 //sinaSSOController.init();

 

  这就解决了密码加密的问题了。

 

2. 模拟请求过程

 

既然知道大致的原理,就可以开始模拟整个登录的过程了, 

 

(1) GET请求 (v1.4.11) 

返回的数据中正则匹配到servertime、nonce和rsakv,注意,在请求的时候要把时间戳也一并传到服务器。我们看看fiddler监控到的QueryString:

 

前五个参数都在URL里面显示声明了,最后的_就自己在发请求的时候补上,传过去吧。

我使用的是Javascript,用Jquery,$.ajax中的data属性里面加进去就好了。

 

(2) POST请求 (v1.4.11) 提交登录表单

 

 1  agent('(v1.4.11)', 
 2                     {type: 'POST', headers: { Referer : ''},
 3                         data : {
 4                             entry:'weibo',
 5                             gateway:1,
 6                             from:'',
 7                             savestate:7,
 8                             useticket:1,
 9                             pagerefer:'',
10                             vsnf:1,
11                             su:'MTgxMDU0MjMzNyU0MHFxLmNvbQ==',
12                             service:'miniblog',
13                             servertime: servertime,
14                             nonce: nonce,
15                             pwencode:'rsa2',
16                             rsakv: rsakv,
17                             sp: sp,
18                             encoding:'UTF-8',
19                             prelt:505,
20                             url:'',
21                             returntype:'META'
22                         }
23                 }, function(err, data){ ... });

 

  agent是发送请求事务的封装模块,重点看里面的data对象,其中su是base64加密的用户名,每次调用都是固定的,因此写死在这里;

servertime、nonce、rsakv都是在前一步截取的;

sp是加密后的密码,参考上文的加密方式可得。

(代码会在后面分享出来)

 

(3) 上一步页面请求完成后,返回的数据如下所示

 

这段代码执行后,页面直接跳转到新的地址上,虽然我们上微博的时候感觉不到有中间页面的跳转,

其中retcode是从服务器返回过来的,为0时才表示正确,能继续访问,如果返回的是其它值,可以看看ssologin.js的源码,里面有各种错误的说明,

本人也在这个地方纠结了很久,之前尝试都是2092(好像是),后来把前面两步的参数传完整(如_),补上Referer,就好了。所以要尽量模拟完整。 

 

第三步就是要截取这个URL,请求之。至此,登录操作完成。

 

(4) GET请求  ,这是个人主页,能返回个人信息则表示前面的操作成功了,如果是返回登录页,那不好意思,前面的步骤还是再检查一下吧~

 

 

 参考文章:

老版本新浪,Python

老版本新浪,PHP

新版本新浪,Python http://www.cnblogs.com/mouse-coder/archive/2013/03/03/2941265.html

JQuery Ajax API

ChromeExtension https://developer.chrome.com/extensions/webRequest.html#event-onHeadersReceived
 

 

:代码 http://files.cnblogs.com/sysuys/weiboLogin.rar

说明:

1. 这几个文件是从爬虫项目抽取出来的,所以这些文件跑不起来,但可供参考,代码没有完善,没注释

2. 项目是运行在Chrome插件中的

3. 使用了requirejs.js 

阅读(1767) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~