使用 Ruby r实现如何登录新浪微博
看了网上有用 Python 登录的,不过有点过时了,现在加密算法也变了,所以就想自己写一个登录程序。
然后把 ruby 也移植到我的 Linux 开发板上,然后就可以定时登录.......
,
原来一直想用 PHP 实现,可以PHP 操作 http 用 curl 库,总觉着别扭,不够强大!
登陆分为 三步
1:prelogin
发送用户名,密码前,先从新浪服务器获取 三个主要的变量
- servertime
- nonce
- rsakv(RSA的Public Key,下一步用这个public key 加密密码)
- #pre login
- preloginurl = 'http://login.sina.com.cn/sso/prelogin.php?entry=sso&' +
- 'callback=sinaSSOController.preloginCallBack&su=' +
- 'dW5kZWZpbmVk' + '&rsakt=mod&client=ssologin.js(v1.4.2)' +
- "&_=" + Time.now.to_i.to_s
- #puts preloginurl
- res = HttpGet(preloginurl)
- keys = res.body[/\{\"retcode[^\0]*\}/]
- returnfalseif keys == nil
- keys = JSON.parse(keys)
- returnfalseif keys == nil
- returnfalseif keys['retcode'] != 0
#pre login preloginurl = 'http://login.sina.com.cn/sso/prelogin.php?entry=sso&' + 'callback=sinaSSOController.preloginCallBack&su=' + 'dW5kZWZpbmVk' + '&rsakt=mod&client=ssologin.js(v1.4.2)' + "&_=" + Time.now.to_i.to_s #puts preloginurl res = HttpGet(preloginurl) keys = res.body[/\{\"retcode[^\0]*\}/] return false if keys == nil keys = JSON.parse(keys) return false if keys == nil return false if keys['retcode'] != 02:login
login 过程中使用 Http Post,Post 的数据主要有:
- logindata={'entry'=>'weibo', 'gateway'=>'1',
- 'from'=>'', 'savestate'=>'7', 'userticket'=>'1',
- 'ssosimplelogin'=>'1', 'vsnf'=>'1', 'su'=>'',
- 'service'=>'miniblog', 'servertime'=>'', 'nonce'=>'',
- 'pwencode'=>'rsa2', 'rsakv'=>'', 'sp'=>'',
- 'encoding'=>'UTF-8', 'prelt'=>'115',
- 'returntype'=>'META',
- 'url'=>'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack'
- }
logindata={'entry'=>'weibo', 'gateway'=>'1', 'from'=>'', 'savestate'=>'7', 'userticket'=>'1', 'ssosimplelogin'=>'1', 'vsnf'=>'1', 'su'=>'', 'service'=>'miniblog', 'servertime'=>'', 'nonce'=>'', 'pwencode'=>'rsa2', 'rsakv'=>'', 'sp'=>'', 'encoding'=>'UTF-8', 'prelt'=>'115', 'returntype'=>'META', 'url'=>'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack' }
2.1 先使用第一步得到的数据 keys 填充 logindata
- logindata['servertime'] = keys['servertime']
- logindata['nonce'] = keys['nonce']
- logindata['rsakv'] = keys['rsakv']
- logindata['su'] = Base64.strict_encode64(uname.sub("@","%40"))
logindata['servertime'] = keys['servertime'] logindata['nonce'] = keys['nonce'] logindata['rsakv'] = keys['rsakv'] logindata['su'] = Base64.strict_encode64(uname.sub("@","%40"))
logindata['su'] 中是经过 Base64 编码过的用户名
其中 Base64.strict_encode64 是 ruby1.9 以后出现的,使用 ruby1.8 中的 Base64.encode64 会多出来换行符,需要自己去掉2.1 生成RSA 加密过的密码
- pwdkey = keys['servertime'].to_s + "\t" + keys['nonce'].to_s + "\n" + pwd.to_s
- pub = OpenSSL::PKey::RSA::new
- pub.e = 65537
- pub.n = OpenSSL::BN.new(keys['pubkey'],16)
- logindata['sp'] = pub.public_encrypt(pwdkey).unpack('H*').first
pwdkey = keys['servertime'].to_s + "\t" + keys['nonce'].to_s + "\n" + pwd.to_s pub = OpenSSL::PKey::RSA::new pub.e = 65537 pub.n = OpenSSL::BN.new(keys['pubkey'],16) logindata['sp'] = pub.public_encrypt(pwdkey).unpack('H*').first
2.2 Post 数据,并检查是否登录成功
- res = HttpPost(uri,logindata,hdrs)
- #puts 'save cookie'
- redrecturi = res.body[/http:\/\/weibo.com\/ajax[^'"]*/]
- retcode = redrecturi.match(/retcode=([\d]+)/)
- retcode = retcode[1] if retcode != nil
- returnfalseif redrecturi == nil
- retcode = retcode.to_s
- if retcode.to_s != '0'
- reason = redrecturi.match(/reason=([^&]+)/)
- reason = reason[1] if reason != nil
- reason = URI.unescape(reason)
- reason = @iconvFromGB2312.iconv(reason)
- puts reason
res = HttpPost(uri,logindata,hdrs) #puts 'save cookie' redrecturi = res.body[/http:\/\/weibo.com\/ajax[^'"]*/] retcode = redrecturi.match(/retcode=([\d]+)/) retcode = retcode[1] if retcode != nil return false if redrecturi == nil retcode = retcode.to_s if retcode.to_s != '0' reason = redrecturi.match(/reason=([^&]+)/) reason = reason[1] if reason != nil reason = URI.unescape(reason) reason = @iconvFromGB2312.iconv(reason) puts reason
- end
end
- <SPAN style="WHITE-SPACE: pre"> </SPAN>return retcode if retcode != '0'
- <SPAN style="WHITE-SPACE: pre"> </SPAN>returnfalseif !@cookies.GetCookie('SUP','sina.com.cn')
return retcode if retcode != '0' return false if !@cookies.GetCookie('SUP','sina.com.cn')其中 @iconvFromGB2312 只字符转码,Ruby1.9.3 以后的版本可能要移除,转移到String 类下面了,定义如下
- @iconvFromGB2312=Iconv.new('UTF-8','GB2312')
@iconvFromGB2312=Iconv.new('UTF-8','GB2312')@cookies 是一个管理 Http 中 cookie 的自定义类, 在 HttpPost 和 HttpGet 中自动生成、记录了http 传输过程中需要的cookie
3: 完成登录
上步登录成功以后,会在返回的 body 中包含要转到的链接,这一步骤跟随该链接,获取用户基本的信息,并最终访问 http://weibo.com/login.php 完成登录
- <SPAN style="WHITE-SPACE: pre"> </SPAN>res = HttpGet(redrecturi)
- ujson = res.body[/\{\"result\"\:[^)]+\}/]
- returnfalseif ujson == nil
- rval = JSON.parse(ujson);
- returnfalseif rval.has_key?('userinfo') == false
- returnfalseif rval.has_key?('result') == false
- returnfalseif rval['result'] == false
- @userInfo = rval['userinfo']
- HttpGet('http://weibo.com/login.php');
- returntrue
res = HttpGet(redrecturi) ujson = res.body[/\{\"result\"\:[^)]+\}/] return false if ujson == nil rval = JSON.parse(ujson); return false if rval.has_key?('userinfo') == false return false if rval.has_key?('result') == false return false if rval['result'] == false @userInfo = rval['userinfo'] HttpGet('http://weibo.com/login.php'); return true
Ruby 还用不熟悉,只是也是网上东拼西凑的,不系统,所以用着Ruby 语言,却不是使用 Ruby Way 实现的,有点惭愧,各位觉着有用也就大概看下微博登录的方法吧,编程风格是完全不可取的!再此申明,免担误导之责 ,不过还是真心希望 Ruby 大牛,能指正一下!
浙公网安备 33010602011771号