关于node.js 验证 Oauth1.0 接口
下面的node.js调用Oauth接口并不是针对 腾讯开放平台.....具体不同的服务商可能在 oauth 基础上添砖加瓦,还要考虑具体的业务需求.
相比Oauth2.0来说,Oauth1.0真的很繁琐......
但是实际应用中碰到这个问题只能去解决,而不可能给对方打电话说,你赶紧把Oauth协议升级到2.0吧,1.0太繁琐,你想想将会发生什么事情 $#(+)&*@!!
常常涉及到三方:
Service Provider:服务提供者(如 腾讯,只是假设)
Consumer:消费⽅,外部第三⽅方平台(如 一介布衣)
User:用户 (登录用户)
当然我的博客不是多用户博客,只是举例.
前提条件:
在服务提供者平台申请到 appkey 和 secret
应用场景:
登录入口在服务方 (腾讯某个页面加入放置了 一介布衣 登录入口) 点击后页面在腾讯服务器打开,登陆后跳转到一介布衣,一介布衣得到需要的参数然后实现免登陆.
登录入口在第三方 (一介布衣 博客有个按钮,使用QQ帐号登录) 点击后页面跳转到腾讯服务器打开登陆窗口,登陆后再跳转到一介布衣某个地址,获取参数然后实现免登陆.
Oauth1.0调用流程:
1.一介布衣首先请求临时token
2.腾讯返回临时未授权token request_token 给一介布衣
3.一介布衣带上 request_token 去请求授权token authorize_token
4.腾讯返回授权token authorize_token
5.一介布衣带上 authorize_token 去请求具有访问权限的token access_token
6.得到 access_token 后你就有权去调用授权的所有api了
上面的流程真的是痛苦,无助,绝望中......
上面一共需要来回获取3个token ,知道第三个才是有权有效的token,而真正在第一个token拿到手以后,后面的请求都类似.所以集中把获取 request_token 说一下.
OAuth 请求都需要使⽤用 HMAC-SHA1 算法来⽣生成签名.参数需要urlencode ,sign值需要escape .
比如请求url和参数是这样的:
oauth.qq.com/oauth/request_token?a=1&b=2&c=3&d=4&e=****
上面的最后一个参数e 需要把http请求方式(get/post) + 请求地址 + 参数a=1&b=2&c=3&d=4 求 HMAC-SHA1加密后的base64字符串.
实际应用中参数繁琐的很.
需要的必填参数:
oauth_consumer_key (就是appkey)
oauth_nonce (要求无重复字符串可以用时间戳来代替)
oauth_signature_method (加密方法 固定值 HMAC-SHA1)
oauth_timestamp (9位时间戳 此值放在 oauth_signature_method 后面 )
oauth_version (oauth 版本 固定值 1.0)
见代码:
var request=require('request'); var crypto = require('crypto'); var urlencode = require('urlencode'); var querystring = require('querystring'); function request_token(req_url,appkey,secret,callback) { var oauth_nonce = new Date().getTime(); var parameters={ oauth_consumer_key:appkey, oauth_nonce:oauth_nonce, oauth_signature_method:"HMAC-SHA1", oauth_timestamp:Math.round(oauth_nonce/1000), oauth_version:"1.0" }; var kvdatas = []; _.each(_.keys(parameters).sort(), function(key) { //注意,这里要对参数进行排序 kvdatas.push(key + '=' + parameters[key]); }); var query_string = kvdatas.join('&'); var bash_string = urlencode('GET') + '&' + urlencode(req_url) + '&' + urlencode(query_string); var oauth_signature = querystring.escape(crypto.createHmac('sha1', secret + '&').update(bash_string).digest('base64')); request.get(req_url+'?'+query_string+'&oauth_signature='+oauth_signature, function (error, response, body) { if(body){ var rtnObj=querystring.parse(body); //将a=b&c=d 的参数串格式化成object if(rtnObj){ callback(null,rtnObj); } callback(null,null); } }); }
上面封装成一个公用的获取 request_token方法,你能看到所有参数需要 urlencode , oauth_signature 需要 escape ,因为base64有类似 =号,传输后无法识别.
下面看调用:
var request_token_url='http://oauth.qq.com/oauth/authorize_token'; var appkey='你的 app_key'; var app_secret='你的 app_secret'; request_token(request_token_url,appkey,app_secret,function(err,retObject){ console.log('----------',retObject); //上面打印出了retObject ,接着请求第二,第三次,最后拿到有权访问api的 access_token });