经过我一天的研究,新浪微博已不支持oauth1.0的验证了,更新到2.0验证,虽然在FAQ里面写道了,但是TMD 新浪文档里面和SDK里面都有详细的oauth1.0的说明,真是坑爹啊,于是本文对于新浪的吐糟将会大于对于oauth1.0的解释
话说一直以为SDK(android)都很完善,拿来就能用的,知道我膝盖中了一箭。。。虽然SDK中直接用oauth2.0验证是可以直接用的,但是刚刚学习了oauth1.0的我,想实践一下1.0的验证流程,就细看了一下SDK的源码。我差,这SDK写得也太那什么了吧,刚毕业也写得比这好,说好的代码风格呢,有些API写着有一个形参,实现里面却压根没有使用过这个形参,非要先先使用另一个api,才有效,还有一些API对于异常的处理简直就是还不如没有。里面有几个函数逻辑还有错。。。当然这些都是SDK内部的一些bug,你直接使用oauth2.0的接口,还是问题不大的,但是这是在没有异常的情况下,一旦服务器返回错误,你的android程序就挂了(因为没有处理异常)。虽然你不支持oauth1.0了,但是你也不能把1.0接口搞成这样啊,要不就直接能用的,要不直接在sdk把1.0的相关代码删了,这样不明不白的放在sdk里,坑了个大爹啊。今天上午我终于把SDK1.0的接口改成能使用了的了,(本来要不异常,要不就验证签名失败,终于在各种文档的帮助下,我该用好了)。发送给服务器,一如既往的failure,但是签名终于正常了。但是服务器返回forbid to use the basic oauth.坑爹啊。。搞了这么长时间,竟然返回不支持oauth1.0.好吧不支持就不支持了。通过对于SDK的研究,自己也对1.0的认识更深了一层。
Oauth1.0的几个重要东西Request token,callback_url,verifier,access token,request_url。
Request token:应用对于用户请求向服务器发送请求的第一步。
必要的oauth认证参数:cosumer_key,callback_url, 以下几个参数都是自动生成的timestamp,noucne,加密算法,oauth版本
新浪规定也不知道是oauth协议规定,加密字符串base string 必须按文本排序(就是abcd排序)。然后前面加上的 http方法名 + “&” + (encoded)url + & + params(这个param包含oauth认证参数+http请求参数),然后用consumer_secret + "&"+ token_secret(get request_token时,还没有token_secret,可以不填,也就是consumer_secret + "&")作为密钥。加密base string,将生成的签名,附于oauth参数后面。发给服务器。
服务器端目测是这样的处理流程:从post中,或者http头部中(貌似新浪放在头部,腾讯放在post中),获取oauth参数和http参数。将其排序,按照相同的方法生成base string,和密钥(服务端知道consumer_secret,token_secret因为是它发给你的,但是别人不知道,于是起到了身份验证的作用)。用相同的算法生成签名,比较签名值,如果签名一样,那么身份验证成功,服务器根据请求该干嘛干嘛。
当request token 请求发出后,如果正常服务器响应一个token回来,这就是request token。
第二步,将新浪提供的用户认证的url + “?consumer_token” = 刚获得的token.tostring。拼成一个url,然后启动一个可以打开该url的应用(如浏览器)。新浪就会弹出认证窗口。。让用户输入账户和密码,并进行授权。如果授权成功,那么服务器会返回一个带token 和 token verifier的url,这个url就是请求request token时的callback url
对于android应用,这个url就是一个可以启动一个activity的intent,如:tyweibo://TestActivity,当然在那个activity的manifest文件中也要有<data: scheme = tyweibo,host = TestActivity/>的声明。
在浏览器启动的activity中,使用 getIntent().getData();获取一个Uri,再调用uri.getQueryParam方法,获得consumer_verifier。
下一步就是获取access token。
请求参数consumer_key,consumer_token,(目前是request token),consumer_verifier(刚刚获得的),自动生成的timestamp,noucne,固定的加密算法和oauth版本。
成功后,服务器返回access_token 和 token_secret。
之后终于可以调用新浪api接口发送微博、获取微博等等了
比如发一条文本微博,接口为statuses/update.json,认证参数一如既往,token变为access token,http参数中要带上微博内容。
如果新浪支持1.0认证的话,那么就能发送成功,但是目前已经不支持了。所以如果签名验证成功,会返回一条错误告诉你,不能用1.0发送。
SDK蛋疼就在于,前面认证代码都是正确的,就是最后发送会抛出异常。SDK有两处致命错误,一处是如果返回码不是json数据,那么导致由于json数据没解析,而err字符串会空,而格式化err字符串时,err为空而抛出异常。
另外一处是每个认证头的生成都有一个全局变量控制,比如request token 时 Utility.setAuthorization(new RequestTokenHeader());
access token 时会Utility.setAuthorization(new AccessTokenHeader());,
但是调用接口却没有对这个全局变量赋值,导致生成认证头会用上次认证头的信息。比如按流程来说的话,发微薄会调用上次获取access token的信息,从而试图获取verifier的值。然后发微薄不需要该值,从而找不到这个值而异常。
后来把verifier加上,发现签名值不对,可能服务器生成的base string 不包含该值,而错误。后来终于整啊整,签名值算正确了,但是却告诉我不支持1.0了,查,我这么辛苦搞了半天,又被坑了个大爹了~~~