OAUTH协议实践yanghaoquan@126.com服务提供方:例如腾讯开放平台。开发者在上边注册以后,获得第三方键值(consumer_key,即$appkey)和第三方密钥(consumersecrect,即$appsecrect);第三方:例如开发者。在服务提供处注册后获得(appkey,appsecrect)请求令牌:第三方用来请求用户授权访问受保护的资源。(授权||取消)访问令牌:第三方用这个令牌代表用户访问其受保护资源实践备注:服务提供方:腾讯社区开放平台用户:QQ用户,已经有腾讯账户的用户。第三方:在社区开放平台上已经注册的应用。第三方在服务提供方腾讯社区开放平台上注册后,服务提供方给第三方了$appkey和$appsecrect;1:使用$appkey和$appsecrect初始化初始化的作用也就是把$appkey和$appsecrect这两个参数赋值给classOpenSDK_OAUTH_Interface的受保护资源变量$_appkey和$_appsecrect。Self:$_appkey=$appkeySelf:$_appsecrect=$appsecrect在classOpenSDK_OAUTH_Interface这个类中对方法和变量都是用了static.使用static静态成员和静态方法,调用静态属性的时候不能使用伪变量$this,只能使用self::,使用static的好处是可以不用实例化直接使用。2:设置完成以后,开启session;Session_start();为了输出汉字;所以使用header()函数告诉浏览器:Header(“content-type:text/html;charset=utf-8”)注意这个跟一般的PHP文件的最开始处的写法:metahttp-equiv=”Content-type”content=”text/html;charset=utf-8”;其实下次使用PHP写测试文件的时候,不要再使用metahttp-equiv=”content-type”content=”text/html;charset=utf-8”,可以使用header(“content-type:text/html;charset=utf-8”);这样更简便一些。3:按下“点击去授权”以后在$_GET这个全局变量中设置:$_GET[‘go_auth’];不过go_auth=string(0);$callback=http://.$_SERVER[‘HTTP_HOST’].$_SERVER[‘PHP_SELF’]产生一个回调页面URL:$callback=http://localhost/QQ/demo/index.php调用Weibo.php文件中的getRequestToken($callback)产生一个请求令牌:$request_token获取OAuth对象:getOauth()Self:$oauth=newOpenSDK_OAuth_Client(self::$appsecrect);跳转到Client.php页面。类里边定义了类常量ConstOAUTH_TOKEN_SECRECT=’tencent_access_token’;4:下一步需要获取request_token:$response=self::request(self::$requestTokenURL,’GET’,array(‘oauth_callback’=$callback))$requestTokenURL::Protectedstaticfunctionrequest($url,$method,$params,$muti=false){If(!self::$_appkey||self::$appsecrect){Exit(‘appkeyorappsecrectnotinit’);}$params[‘oauth_nonce’]=md5(mt_rand(1,100000).microtime(true));$params[‘oauth_consumer_key’]=self:$appkey;$params[‘oauth_singature_method’]=‘HMAC-SHA1’;$params[‘oauth_version’]=self::$version;$params[‘oauth_timestamp’]=self:getTimestamp();Returnself::getOauth()-request($url,$method,$params,$multi);}对经过上一步操作后的封装参数进行签名处理:Publicfunctionrequest($url,$method,$params,$multi=false){$oauth_signature=$this-sign($url,$method,$params);$params[$thgis-oauth_signature_key]=$oauth_signature;Return$this-http($url,$params,$method,$multi);}签名处理:根据strcmp函数比较$params然后排序,Uksort($params,’strcmp’);然后是$key=OpenSDK_Util::urlencode_rfc3986($key);签名处理的最主要任务是对URL进行urlencode处理。获取签名的数据是:接下来产生最关键的$base_string=implode(“&”,array(strtoupper($method),OpenSDK_Util::urlencode_rfc3986($url)),$signature_parts);6:一切就绪,开始向接口发起HTTP请求。获取request_token的方法是GET接口地址:$url(string:42)$urls=parse_url($url);获取的结果是:scheme:httphost:open.t.qq.compath:cgi-bin/request_token解析完成后:$httpurl=$urlpath=$urls[‘path’].($urls[‘query’]?’?’.$urls[‘query’]:’’);//动态请求数据$postdata=implode(“&”,$parts);$httpurl=$httpurl.(strops($httpurl,‘?’)?’&’,‘?’).$postdata;因为使用的是GET方法,所以有:If($method==”GET”){$headers[]=“GET$httpurlHTTP/$version”;//这儿的$httpurl是路径path.不包含scheme和host}$headers[]=’Host’.$host;$headers[]=’User-Agent:OpenSDK-OAuth’;$headers[]=’Connection:close’;图表1未经用户授权的oauth_token之前我觉得使用PHP_CURL来获取数据。弄不清楚curl和套接字关系,后边社区的彭有跟我说其实curl就是socket_streem();$fp=fsocketopen($host,$port,$errno,$errstr,5);//打开主机与客户端的套接字$errno$errstr这两个参数实际上是由host返回给client的。If(!$fp){$error=‘OpenSocketError’;Return‘’;}PS:br/和\r\n这两者有什么区别??\r表示:回车符(ACSII:13或0x0d),就是我们常说的硬回车。\n表示:换行(ACSII:10或0x0a),就是我们常说的软回车。如果是输出给浏览器,就用br/如果是输出到自己的文件里,就用\n,windows下是\r\n\n是源代码换行!br/是网页表现换行!!$this-fwrite($fp,implode(“\r\n”,$headers));往数据流里边写进去用换行符连接起来的$headers数据。获得的$request_token是:7:接下来获取授权URL:getAuthorizeURL($token,$mini=false)授权接口地址:$authorizeURL=''$url(string:83)$urlHeader(“Location:”.$url);图表2授权页面点击授权后的GET:下一步是获取AccessToken值getAccessToken($_GET[‘oauth_verifier’]);publicstaticfunctiongetAccessToken($oauth_verifier=false){$response=self::request(self::$accessTokenURL,’GET’,array(‘oauth_token’=self::getParam(self::OAUTH_TOKEN),‘oauth_verifier’=$oauth_verifier));}1:Oauth认证中获取request_token参数:签名:$oauth_signature=$this-sign($url,$method,$param);$url:是腾讯定义的接口地址:$method=GET;签名方法:sign($url,$method,$params){Return$sign;}签名参数:$params=array();函数返回值:$sign(string:28)ZBrq/b5VGP9OqUxImsupsy3kIVA=表格1签名参数列表参数值oauth_callback(string:34)http://localhost/QQ/demo/index.phpoauth_consumer_key(string:9)801oauth_nonce(string:32)ab137d197a317134b0c377b1oauth_signature_method(string:9)HMAC-SHA1oauth_timestamp(int)1323744422oauth_version(string:3)1.0组装好了请求参数后,开始调用http($url,$params,$method,$multi);函数:functionhttp($url,$params,$method=’GET’,$multi=false)表格2HTTP()函数参数表参数值url接口地址:eg:、GET和DELETE等方法。请求request_token时候是GET方法multi默认false。请求request_token时候是false把所有的参数以URL编码格式组装起来。接下来调用fsockopen($host,$port,$error,$errstr,5)函数:这个函数在客户端和服务器端之间建立一个套接字连接。$fp=fsockopen()后,可以对$fp进行fgets()fwrite()等操作,相当于在里边添加后,发起了HTTP请求,然后从HTTP响