szgzwf

http://www.etsec.com.cn

导航

使用 Ruby r实现如何登录新浪微博

看了网上有用 Python 登录的,不过有点过时了,现在加密算法也变了,所以就想自己写一个登录程序。

然后把 ruby 也移植到我的 Linux 开发板上,然后就可以定时登录....... 大笑,

原来一直想用 PHP 实现,可以PHP 操作 http 用 curl 库,总觉着别扭,不够强大!

 

 

登陆分为 三步

1:prelogin

发送用户名,密码前,先从新浪服务器获取 三个主要的变量

 

  • servertime
  • nonce
  • rsakv(RSA的Public Key,下一步用这个public key 加密密码)

 

[ruby] view plaincopyprint?
  1. #pre login
  2. preloginurl = 'http://login.sina.com.cn/sso/prelogin.php?entry=sso&' +
  3. 'callback=sinaSSOController.preloginCallBack&su=' +
  4. 'dW5kZWZpbmVk' + '&rsakt=mod&client=ssologin.js(v1.4.2)' +
  5. "&_=" + Time.now.to_i.to_s
  6. #puts preloginurl
  7. res = HttpGet(preloginurl)
  8. keys = res.body[/\{\"retcode[^\0]*\}/]
  9. returnfalseif keys == nil
  10. keys = JSON.parse(keys)
  11. returnfalseif keys == nil
  12. 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'] != 0
2:login

 

login 过程中使用 Http Post,Post 的数据主要有:

 

[ruby] view plaincopyprint?
  1. logindata={'entry'=>'weibo', 'gateway'=>'1',
  2. 'from'=>'', 'savestate'=>'7', 'userticket'=>'1',
  3. 'ssosimplelogin'=>'1', 'vsnf'=>'1', 'su'=>'',
  4. 'service'=>'miniblog', 'servertime'=>'', 'nonce'=>'',
  5. 'pwencode'=>'rsa2', 'rsakv'=>'', 'sp'=>'',
  6. 'encoding'=>'UTF-8', 'prelt'=>'115',
  7. 'returntype'=>'META',
  8. 'url'=>'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack'
  9. }
               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

 

[ruby] view plaincopyprint?
  1. logindata['servertime'] = keys['servertime']
  2. logindata['nonce'] = keys['nonce']
  3. logindata['rsakv'] = keys['rsakv']
  4. 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 加密过的密码

 

[ruby] view plaincopyprint?
  1. pwdkey = keys['servertime'].to_s + "\t" + keys['nonce'].to_s + "\n" + pwd.to_s
  2. pub = OpenSSL::PKey::RSA::new
  3. pub.e = 65537
  4. pub.n = OpenSSL::BN.new(keys['pubkey'],16)
  5. 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 数据,并检查是否登录成功

 

 

[ruby] view plaincopyprint?
  1. res = HttpPost(uri,logindata,hdrs)
  2. #puts 'save cookie'
  3. redrecturi = res.body[/http:\/\/weibo.com\/ajax[^'"]*/]
  4. retcode = redrecturi.match(/retcode=([\d]+)/)
  5. retcode = retcode[1] if retcode != nil
  6. returnfalseif redrecturi == nil
  7. retcode = retcode.to_s
  8. if retcode.to_s != '0'
  9. reason = redrecturi.match(/reason=([^&]+)/)
  10. reason = reason[1] if reason != nil
  11. reason = URI.unescape(reason)
  12. reason = @iconvFromGB2312.iconv(reason)
  13. 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
[ruby] view plaincopyprint?
  1. end
		end
[ruby] view plaincopyprint?
  1. <SPAN style="WHITE-SPACE: pre"> </SPAN>return retcode if retcode != '0'
  2. <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')
[ruby] view plaincopyprint?

其中 @iconvFromGB2312 只字符转码,Ruby1.9.3 以后的版本可能要移除,转移到String 类下面了,定义如下

 

 

[ruby] view plaincopyprint?
  1. @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 完成登录

 

[ruby] view plaincopyprint?
  1. <SPAN style="WHITE-SPACE: pre"> </SPAN>res = HttpGet(redrecturi)
  2. ujson = res.body[/\{\"result\"\:[^)]+\}/]
  3. returnfalseif ujson == nil
  4. rval = JSON.parse(ujson);
  5. returnfalseif rval.has_key?('userinfo') == false
  6. returnfalseif rval.has_key?('result') == false
  7. returnfalseif rval['result'] == false
  8. @userInfo = rval['userinfo']
  9. HttpGet('http://weibo.com/login.php');
  10. 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 大牛,能指正一下!

posted on 2012-11-07 10:51  szgzwf  阅读(621)  评论(0)    收藏  举报