飞信2010分析 – SSI登录
一个月前,移动飞信发布了飞信2010版,也就是V3.6版(飞信2008版为V3.5),并升级了飞信的通信协议。飞信2010版最显著的功能更新就是非移动用户也可以使用飞信了,只需使用一个邮箱注册即可。但限制还是比较多的,只能已经开通飞信的人发送消息,注意不是短信,当该用户不在线的时候以离线的消息发送。但可以每个月可以免费发送三条短信,如果要发送更多,还得绑定手机号。。
其实很早就想写关于飞信2010版的内容。在飞信2010发布没几天我就开始分析SSI登录和SIPC验证。SSI登录很快就搞定了,但SIPC验证总是失败。查了很久都没有结果,于是就放了有两周吧。两周后的某一天实在是无聊,翻出以前分析飞信2010的代码,拖出Reflector和VC# Express又分析一通,总算搞定了。。网上关于飞信2010的资料还少,我还是简单的写出来,和大家分享我的飞信的研究心得吧,如果我说得不对,别拍我板砖哈~~
废话少说,简单说下飞信2010版协议的变化:
1、SSi登录使用新的V4版本,地址是:https://uid.fetion.com.cn/ssiportal/SSIAppSignInV4.aspx
2、飞信通信协议版本升级为 SIP/C-4.0,主要的操作协议已经是V4了,比如GetContactInfoV4
3、通信协议中很多地方为了减少流量都简写了,比如presence简写为pr,local-name 简写为l
飞信登录其实是分三步的:第一步获取自适应的系统配置,第二步:SSI登录,第三步:SIPC登录验证。
先说一下第一步,获取自适应的系统配置。
自适应的配置包含了很多和飞信客户端有关的信息。其中里面最重要的一个信息就是飞信服务器的地址。不同的地方的飞信用户登录到了不同的飞信服务器。比如四川的飞信的用户就登录到四川的飞信服务器上。至于为什么需要登录到本地的飞信服务器上,我个人觉得从技术上来说可能是做负载均衡,从运营上来说可能是不同的省的移动子公司的运营方式不同。
完成获取自适应的配置其实很简单,做一个简单的HTTP POST就行了。地址是固定的。参数大部分也是固定的。
地址为http://nav.fetion.com.cn/nav/getsystemconfig.aspx,POST的内容如下
<config><user mobile-no="159xxxxxxxx" /><client type="PC" version="3.6.2000" platform="W5.1" /><servers version="0" /><service-no version="0" /><parameters version="0" /><hints version="0" /><http-applications version="0" /><client-config version="0" /><services version="0" /></config>
如果模拟飞信客户端登录,只需改变一下mobile-no,其他可以全不变。
POST /nav/getsystemconfig.aspx HTTP/1.1 User-Agent: IIC2.0/PC 3.6.1860 Host: nav.fetion.com.cn Content-Length: 286 Connection: Close <config><user mobile-no="159xxxxxx" /><client type="PC" version="3.6.1860" platform="W5.1" /><servers version="0" /><service-no version="0" /><parameters version="0" /><hints version="0" /><http-applications version="0" /><client-config version="0" /><services version="0" /></config> HTTP/1.1 200 OK Connection: close Date: Thu, 04 Mar 2010 15:22:04 GMT Server: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 2.0.50727 Cache-Control: private Content-Type: text/html; charset=utf-8 Content-Length: 13319 <?xml version="1.0" encoding="utf-8" ?> <config carrier="CMCC"> <servers version="117"> <ssi-app-sign-in-v2>https://uid.fetion.com.cn/ssiportal/SSIAppSignInV4.aspx</ssi-app-sign-in-v2> <get-pic-code>http://nav.fetion.com.cn/nav/GetPicCodeV4.aspx</get-pic-code> <web-cm-service-url>http://www.sc.chinamobile.com</web-cm-service-url> <sipc-proxy>221.130.46.141:8080</sipc-proxy> <sipc-ssl-proxy>221.130.46.141:443</sipc-ssl-proxy> <http-tunnel>HTTP://221.130.46.141/ht/sd.aspx</http-tunnel> <get-uri>http://hdss1cska.fetion.com.cn/HDS_Pool05/geturi.aspx</get-uri> <sub-service>https://nav.fetion.com.cn/nav/Subscribe.aspx</sub-service> <ssi-app-sign-in>https://uid.fetion.com.cn/ssiportal/SSIAppSignIn.aspx</ssi-app-sign-in> <ssi-app-sign-out>http://ssi.fetion.com.cn/ssiportal/SSIAppSignOut.aspx</ssi-app-sign-out> .. </server> ... </config>
下面开始分析飞信2010版的SSi登录部分。
什么是SSI呢? 我个人理解就是Single Sign-In,就是单点登录。
做过大型网站都会存在这样一个问题,网站有很多的应用,但都需要用户登录验证时才能使用服务。但往往这些应用都在不同的服务器,一个用户登录了这个应用,但打开另一个应用却又需要用户登录验证,因为在不同的服务器,彼此之间是独立的状态。为了达到用户在一个应用登录之后就可以自动的登录其他的应用,可以设置一个专一登录服务器,如果用户登录之后,就把这个状态推送到各个应用服务器,或者应用服务器在用户访问的时候主动向登录服务器询问当前用户是否登录。这个实现方法可以不同。
飞信应该采用的是第二种实现方案。飞信其实是一种混合多种软件体系结构的一个软件。比如飞信客户端通信采用的C/S软件体系结构,而获取用户头像,传输文件等却又是面向SOA的软件体系结构(如HTTP,SOAP,REST,飞信是用的HTTP建立的应用)。为了在这不同的软件体系结构共享用户状态,就必须要设置一个登录服务器来完成用户登录操作,然后返回一个用户标志,这就是SSIC(Single Sign-In Credential),比如获取用户定义的头像,事实上就是一个HTTP的应用,但HTTP是无状态的,如何让服务器判断这个请求是否合法呢?这里就需要把SSI登录成功的SSIC作为Cookie传递给服务器帮助判断请求是否合法。如果是基于HTTP传输模式的话,这个SSIC是放在Cookie中的。
飞信是怎么实现SSI的呢?其实很简单,做个HTTPS的GET就行了。在飞信2006的时候,使用的SignV1就直接把用户手机号和原始密码作为两个参数传递过去就行了,但飞信2008的就用了SignV2,新增了验证图片验证,可以防止恶意程序猜测密码,并且支持把密码加密后作为digest传递过去,保障了安全性。到飞信2010启用了SignV4验证,同样有验证码验证,并且改变了密码的加密方式。
下面就详细的说明飞信2010采用的SignV4的SSI登录的过程和加密方法。
SSI登录的地址是:https://uid.fetion.com.cn/ssiportal/SSIAppSignInV4.aspx
简单的说下参数,以GET方式传递,就目前发现的有八个
mobile:手机号
sid:飞信号
domains:获取SSIC的域名,不同的域名以分号(;)分开。不同的域名的SSIC是不同的,这里飞信客户端默认传递了三个域名:fetion.com.cn%3bm161.com.cn%3bwww.ikuwa.cn这三个域好像都是移动的域名。。
v4digest-type:加密的方式。可以取两个值 1:V4Temp,2:V4
v4digest:加密后的密码,以16进制表示,20字节
pid:验证码图片编号
pic:用户输入的验证码
algorithm:图片生成算法(这个待验证,我觉得更像是验证原因…)
其中飞信号和手机号有且只能有一个,必须的。(这两个参数都传递是什么结果我还没试过呢)。
domains也是必须的,默认值为fetion.com.cn%3bm161.com.cn%3bwww.ikuwa.cn
v4digest-type和V4digest也是必须的。
下面的三个参数:pid,pic,algorithm只有在需要用户输入验证码验证才有效,而且三者都是必须的。如果不需验证,则可以不传递。
当v4digest-type=1时,v4digest的算法很简单,就是把 字符串 “fetion.com.cn:”的UTF8编码的字节数组和用户明文密码的UTF8字节编码数组连接在一起,然后计算SHA1的值就是加密结果。
主要加密代码如下:
public static String encryptV4(String plainpass)
{
return doHash(ConvertHelper.string2Byte("fetion.com.cn:"), ConvertHelper.string2Byte(plainpass));
}
当v4digest-type=2 时,v4digest的算法就需要用到userid和v4digest-type=1时加密密码后的结果。userid是一个整型数,把userid转换为字节数组,注意低字节在前。然后和用v4digest-type=1时加密结果转换为字节数组连接在一起,再计算SHA1的值就是加密结果了。 主要加密代码如下:
public static String encryptV4(int userid, String plainpass)
{
String passHex = encryptV4(plainpass);
return doHash(ConvertHelper.int2Byte(userid), ConvertHelper.hexString2ByteNoSpace(passHex));
}
这是加密用的工具函数,就是把两个字节数组合成一个数组然后计算这个数组的SHA1的值,返回的是16进制的字节字符串
private static String doHash(byte[] b1, byte[] b2)
{
byte [] dst = new byte[b1.length+b2.length];
System.arraycopy(b1, 0, dst, 0, b1.length);
System.arraycopy(b2, 0, dst, b1.length, b2.length);
byte[] res = DigestHelper.SHA1(dst);
return ConvertHelper.byte2HexStringWithoutSpace(res);
}
当然用户第一次登录时只有飞信号或者手机号,所以就直接使用v4digest-type=1加密方法就行了,但如果知道了用户的userid就可以使用v4digest-type=2的加密方式了,比如登录成功之后网络断了的重登录。 如果服务器返回的状态码是200,表明验证成功,这个时候就会传回用户的uri,userid,还有最重要的ssic,注意这个ssic是作为一个cookie返回的,并没有在返回的正文中。其他的数据我也还没有分析,不过是XML的,很容易理解,这里不说了。 当然服务器可能会返回其他的状态码,这里列出一部分。
401:密码错误;
420:输入的验证码不正确;
421:当前登录的用户需要图片验证;
424:登录尝试超过规定次数;
431:用户正在更换飞信号,暂时无法登陆
432:用户已启用新的飞信号,当前飞信号已停止使用
435:您未绑定安全邮箱或手机号
GET /ssiportal/SSIAppSignInV4.aspx?mobileno=159xxxxxx&domains=fetion.com.cn%3bm161.com.cn%3bwww.ikuwa.cn&v4digest-type=1&v4digest=66F6B084EC004E25078CF6626AF05E881403C27E HTTP/1.1 User-Agent: IIC2.0/PC 3.6.2000 Host: uid.fetion.com.cn Connection: Keep-Alive HTTP/1.1 200 OK Date: Sat, 03 Apr 2010 08:39:11 GMT Server: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 2.0.50727 Set-Cookie: ssic=DhIOAABEcX+O5EqnUrCfZQD2/PYXJ12j8mxBOzEiWMJiRzhlfqVrxprxQJcNhAvtusbjSqsJtUq9bX4D+POJlWEyXWDFkCbfR0qwJCbj6z0HnylkvjJ5GkiwMFAVA3bVD8AAeJ0AAA==; path=/ Cache-Control: private Content-Type: text/html; charset=utf-8 Content-Length: 714 <?xml version="1.0" encoding="utf-8" ?> <results status-code="200"> <user uri="sip:123456789@fetion.com.cn;p=6721" mobile-no="159xxxxx" user-status="101" user-id="987654321"> <credentials> <credential domain="fetion.com.cn" c="CBIOAABAyrAQQWMLS1Ze6Auwn01TCYTf4zAc9KVcfkQMWc1hrQrkhe1vXI9xYrrSQUDfK5Ys/af/zLYdK2iwvSmELkTj2sBBtEL1w5vpLguHLWyH5I6+OkRM7nP9+l6PEiQi2eQAAA==" /><credential domain="m161.com.cn" c="CRAOAAA4C0dsXXdiP82bkjsB9aGA1L1wNAaXmqddFRx04Dk7uDCZMyri+OTJdwbTMQF0cckDbSgHVNEkcYBIGc8NJspEPxWzykMOGli8/m+mStMo2w==" /><credential domain="www.ikuwa.cn" c="CBAOAADDAL1rw2Z0QfyhPSiV/g6BkYjWdCyjDMKKqk3RAWETHRVdH3VwLRxD23TMwrCQ2Hk4LBAieDPC4h2RfK3uTLlKysCd62ZZ44cuth7iiThXtA==" /> </credentials> </user> </results>
当SSI登录时返回了421,当前登录操作就需要验证图片验证。新版V4的协议在SIPC验证注册的过程中也加入的图片验证的过程,获取验证图片也是同样的地址。
验证图片的获取是用另外的URL,地址是http://nav.fetion.com.cn/nav/GetPicCodeV4.aspx。方法为GET。
参数就一个,就是验证图片的算法。(从字面上来说是这样,但这里说的可能不准确,我感觉应该是获取验证码的原因。。)
目前可能的取值为:picc-ChangeMachine,picc-PasswordErrorMax。不过不用担心,这个参数在需要验证的时候都可以得到,比如SSI登录的时候,需要验证的时候通常都会把这个参数写入返回的结果里,请各位自行分析了,很简单。
直接发起这样的HTTP请求然后就可以获得验证图片信息。返回的是XML,很容易读取,其中/results/pic-certificate@id就是图片的编号,以后服务器验证用户输入是否正确就需要这个图片编号。/results/pic-certificate@pic就是经过base64编码过后的图片,应该是png格式的。使用base64解码过后就是图片的二进制代码,保存至文件或者渲染到图片框里就可以了。
GET /nav/GetPicCodeV4.aspx?algorithm=picc-ChangeMachine HTTP/1.1 User-Agent: IIC2.0/PC 3.6.1860 Host: nav.fetion.com.cn HTTP/1.1 200 OK Date: Thu, 04 Mar 2010 15:22:08 GMT Server: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 2.0.50727 Cache-Control: private Content-Type: text/html; charset=utf-8 Content-Length: 3113 <?xml version="1.0" encoding="UTF-8"?> <results> <pic-certificate id="ffe70af4-9748-46ce-ba94-0a900da0674d" pic="/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGB......." /> </results>
注意这里一定要设置User-Agent: IIC2.0/PC 3.6.2000,不然会出错。
飞信2010版的SSI登录分析到这,下篇文章分析SIPC 验证和注册。


分析的非常透彻,顶!!
期待您的下篇文章!
[回复]
还有个问题,我想订阅您的博客,可是订阅到的内容好像不是博客的内容。。。
[回复]
@Terry
呵呵,多谢支持,以前那个模板问题太多了,现在换了个模板,可以订阅了哈~
[回复]
分析的太好了,以后研究2010还望多多指教啊!
[回复]
@小球球
呵呵~ 欢迎一起研究飞信哈~
[回复]
我想问一下,你用什么软件看得到SSI登陆时包的数据字段?我用的sniffer和wireshark,看到的都是乱码!
[回复]
solosky 回复:
五月 21st, 2010 at 9:56 下午
HttpAnalyzer, 在这篇文章有下载链接,http://www.solosky.net/2010/03/the-fetion-resources.html。
[回复]
能不能写一个php的密码加密
[回复]
师兄可以弄一个PHP的不? 你这个应该有很多人看不懂的。
[回复]
doyle 回复:
八月 2nd, 2010 at 10:04 下午
不会PHP怎么办?也有很多人看不懂PHP的啊
[回复]
omyweb 回复:
八月 3rd, 2010 at 9:06 上午
师兄还是弄一个PHP的嘛
[回复]
solosky 回复:
八月 3rd, 2010 at 9:10 上午
PHP版的网上有高手写了个,网址在这,http://openfetion.sourceforge.net/,目前已经无法登录了,如果你有兴趣可以自行修改,我如果有时间的话也会修改下,敬请留意。
一直在找能取得好友的PHP 飞信API 但是一直没有找到 所以过来了 ~ 以后常来~
[回复]
感谢你的详细分析。
我正在用python写一个fetion小工具来练习,目前SSI这一步已经完成(也碰到了验证码)
[回复]
Sutra 回复:
九月 10th, 2010 at 2:16 上午
Pyfeton 版本的:
http://nav.fetion.com.cn/nav/GetPicCodeV4.aspx
[回复]
SSi登录使用新的V4版本,地址这个是该怎么找到的?
[回复]
有没有分析过手机fetion了,好像协议有些不太一样
[回复]
终于成功了~谢谢你提供到资料~~
[回复]
我用C#实现的,ConvertHelper这个东西没有啊?
[回复]
public LoginState signIn(User user, VerifyImage img) 执行这个函数 int status = conn.getResponseCode(); 方法的时候 有一定记录会抛出 IOException e 异常。 各位有没有碰到过。。在线等啊。。~~急急急急急急急!!!
[回复]
solosky 回复:
五月 12th, 2011 at 1:08 下午
恩,这个的确有一定的几率,不过这个是由于飞信的SSI服务器不太稳定造成的,请多尝试几次就可以了。
[回复]
异常 java.net.UnknownHostException: Host is unresolved: uid.fetion.com.cn:443
备注 我的帐号 密码 都是正确的。。 急急急急急急急急急急急急急急~~
[回复]
solosky 回复:
五月 12th, 2011 at 1:06 下午
出现这个错误明显是网络连接失败,请检查你的网络是否能访问互联网。
[回复]
这个问题一旦出来以后 从新启动手机 在登录就不会出现。。
[回复]
kenken 回复:
五月 10th, 2011 at 7:31 下午
每次登陆就显示登陆失败,错误代码是10013404 SSI登录失败,返回码:404,求助啊,谢谢
[回复]
solosky 回复:
五月 12th, 2011 at 1:09 下午
请使用maplfetion-2.5.xx的版本。
[回复]
而且网卡还显示未知错误
[回复]
grps 与wifi 切换 会出线无法登录的情况。 大家有遇到过吗?
[回复]
solosky 回复:
五月 12th, 2011 at 1:05 下午
你好,经过和我一个朋友的讨论, 切换网络后,client会感知到,并会回调NotifyEventListener中的ClientStateEvent,客户端状态会改变为NET_ERROR,此时需要等待一段时间再尝试登陆。只要客户端出现了错误会自动释放资源,不需要额外清空什么内容,直接重新登陆就行。
另外一般切换网络后,都要一定的时间网络才可用,所以建议你等一段时间再尝试登陆。
[回复]
xd你有email吗,想跟你讨论讨论~
[回复]
solosky 回复:
五月 28th, 2011 at 9:45 下午
XD啥东东? 我Email:solosky772@qq.com,欢迎一起探讨。
[回复]
我环境需要一个代理才能连接外网,但是测试的时候卡在第二步ssi验证的时候过不去了,请大侠指点!
[回复]
来新媒传信吧
[回复]
呵呵,支持支持,还是初级阶段,以后多来逛逛
[回复]
[url=http://members.americanangler.com/dertyxewer]Tramadol cod next day[/url]
[url=http://members.americanangler.com/omredwuks]Colchicine with no prescription[/url]
[url=http://www.communitywalk.com/buy-tramadol-saturday]acetaminophen per tramadol hcl uthscsa [/url]
[url=http://www.communitywalk.com/overnight-delivery-cialis]cialis discount online failed [/url]
[url=http://www.formspring.me/odrukov67]Amitriptyline Online[/url]
[url=http://members.americanangler.com/klasroud]Ultram no rx overnight[/url]
[url=http://www.formspring.me/fonpilk49]generic viagra online US should [/url]
[url=http://members.americanangler.com/nuskoerd]Soma overnight[/url]
[url=http://www.womensnet.org.za/node/30239]soma buy on line dirIdx [/url]
[回复]
一个代理才能连接外网,但是测试的时候卡在第二步ssi验证的时候过不去了,请大侠指点!
[回复]
gwmold 回复:
二月 29th, 2012 at 4:25 下午
maplefetion.default.properties增加以下内容
host-proxy=true
host-ip=10.1.1.1
host-port=8080
openConnection()变更为以下形式:
Boolean host_proxy=FetionConfig.getBoolean(”host-proxy”);
String host_ip=FetionConfig.getString(”host-ip”);
Integer host_port=FetionConfig.getInteger(”host-port”);
SocketAddress addr= new InetSocketAddress(host_ip, host_port);
Proxy proxy = new Proxy(Proxy.Type.HTTP, addr);
HttpURLConnection conn =null;
if(host_proxy = true){
conn = (HttpURLConnection) url.openConnection(proxy);
}else{
conn = (HttpURLConnection) url.openConnection();
}
我已测试成功。
[回复]
dygqgtpmptlz, Viagra for sale, LoHsWut, [url=http://bryc3.com/]Discount viagra[/url], irstBmJ, http://bryc3.com/ Canadian viagra, AceRtqx.
[回复]