oauth2.0初体验

原创
2013/03/12 17:16
阅读数 8.2K

什么是OAuth2.0?

 
维基百科里有很好的说明 http://zh.wikipedia.org/wiki/OAuth 
现在OAuth2.0协议的应用已经非常广泛,比如我们常用到的在团购网或论坛上用qq号或者微博账号直接登录,就是用OAuth2.0协议实现的.

 

按照以上流程,OAuth2.0协议的服务端和客户端实现并不困难,一个一般水平的程序员完全可以自己编写~
如果不愿自己花精力,可以使用网上的开源类库.

本次测试使用的服务端类库下载地址:http://code.google.com/p/oauth2-php/
测试可以在同一域名下进行,也可以在不同域名下进行,因为服务端可以不用session和cookie,不涉及到域的问题.
此服务端支持mysql和mongodo两种数据库,本次测试使用mysql数据库,数据库连接扩展需要用pdo_mysql.
为了让测试结果更加直观,服务端域名用server.com客户端域名用client.com

服务端的搭建

     

  1.  把下载的源码包解压到web程序路径下.
  2.  oauth2-php/server/examples/pdo/mysql_create_tables.sql 这个sql文件里放的是服务端要用的数据表,手动把它导入到数据库中.
  3.  打开oauth2-php/server/examples/pdo/lib/PDOOAuth2.inc,最上面几行常量是mysql的连接配置,修改它.我用的这个版本,第13行是
include "../../../lib/oauth.php";

 这个引用地址不对,要改成

include '../../../lib/OAuth2.inc';

这样服务端就搭建完成了.

客户端搭建

 
由于是第一次使用OAuth2.0协议,我对它不是很熟悉,写客户端费了不少功夫.
主要参考的是腾讯网的调用说明:http://wiki.opensns.qq.com/wiki/%E3%80%90QQ%E7%99%BB%E5%BD%95%E3%80%91%E5%BC%80%E5%8F%91%E6%94%BB%E7%95%A5_Server-side 
测试不通的时候就在客户端代码中加断点调试.这个服务端的报错不是很友好,但代码很容易看懂.

1.在服务端添加客户端授权

访问http://server.com/oauth2-php/server/examples/pdo/addclient.php 注册客户端.
客户端id和密钥需要写长一些,最短3个字符,否则验证时会出错.
Redirect URI这一项可以填写http://client.com,它必须是客户端所有数据传送页面地址的前缀,所以不能写成http://client.com/index.php这样.

2.在客户端增加几个测试页面

common.php,存放配置信息

<?php
error_reporting ( E_ALL - E_NOTICE );
session_start ();
// 应用的APPID
$app_id = "1111111111";
// 应用的APPKEY
$app_secret = "2222222222";

step1.php,这个页面用于把用户带到服务端的用户授权页面,服务端的用户授权页面

<?php
include("common.php");
// 成功授权后的回调地址
$my_url = "http://client.com/step2.php";
// Step1:获取Authorization Code
$code = $_REQUEST ["code"];
if (empty ( $code )) {
	// state参数用于防止CSRF攻击,成功授权后回调时会原样带回
	$_SESSION ['state'] = md5 ( uniqid ( rand (), TRUE ) );
	// 拼接URL
	$dialog_url = "http://server.com/oauth2-php/server/examples/pdo/authorize.php?response_type=code&client_id=" . $app_id . "&redirect_uri=" . urlencode ( $my_url ) . "&state=" . $_SESSION ['state'];
	
	echo ("<script> top.location.href='" . $dialog_url . "'</script>");
}

step2.php,这个页面用于接收服务端传送回来的临时令牌,并用此令牌获取服务端的访问令牌

<?php
include("common.php");
// 接收上一步返回的错误信息
if ($_REQUEST ['error'])
	die ( $_REQUEST ['error'] );
// 用于发送post请求的方法,取得访问令牌需要用post请求
function http_post($url, $data) {
	$data_url = http_build_query ( $data );
	$data_len = strlen ( $data_url );
	return array ('content' => file_get_contents ( $url, false, stream_context_create ( array ('http' => array ('method' => 'POST', 'header' => "Connection: close\r\nContent-Length: $data_len\r\n", 'content' => $data_url ) ) ) ), 'headers' => $http_response_header );
}
// code是服务端返回的临时令牌
$code = $_REQUEST ["code"];
// Step2:通过Authorization Code获取Access Token
if ($_REQUEST ['state'] == $_SESSION ['state']) {
	$re = http_post ( "http://server.com/oauth2-php/server/examples/pdo/token.php", 
		array (
			'client_id' => $app_id, 
			'client_secret' => $app_secret, 
			'code' => $code, 
			'grant_type' => 'authorization_code', 
			// redirect_uri一定要是当前页面的地址,否则会认证失败
			'redirect_uri' => 'http://client.com/step2.php' 
		)
	 );
	$re = ( array ) json_decode ( $re ['content'] );
	if($re['access_token'])
	{
		$_SESSION['access_token']=$re ['access_token'];
		echo "访问令牌是:".$re ['access_token'],"<br /><a href='step3.php'>访问受保护的资源</a>";
	}
	else
	{
		echo "获取令牌失败!";
	}
}

step3.php,这个页面用来获取服务端的受保护资源,并输出出来  

<?php
include("common.php");
//资源地址
$url = "http://server.com/oauth2-php/server/examples/pdo/protected_resource.php".
		"?oauth_token=" . $_SESSION['access_token'];
//获取到的受保护资源内容
if($content = file_get_contents ( $url ))
	echo "以下是获取到的受保护内容:<br />",$content;
else 
	echo "获取资源失败!";

搭建完成后访问客户端的step1.php,http://client.com/step1.php进行测试

执行顺序说明

   

  1. 最先访问http://client.com/step1.php
  2. 上一个页面,自动跳转到http://server.com/oauth2-php/server/examples/pdo/authorize.php 这个服务端页面,用户在这个页面上授权,让客户端可以访问他在服务端存放的数据(受保护的资源,如用户信息等).这一步可以根据需要分成多步,比如先让用户登录,再显示授权页面.
  3. 上一个页面自动跳转到 http://client.com/step2.php 并传递回来一个临时令牌($_REQUEST ["code"]).由于这个令牌是在浏览器中传输的,它的寿命比较短,客户端必须马上用它换取访问令牌,访问令牌的寿命比较长.
  4. http://client.com/step2.php 此页面把临时令牌用post请求发送到 http://server.com/oauth2-php/server/examples/pdo/token.php 获取访问令牌,并把访问令牌存到session中,此令牌在服务端的寿命是1小时.
  5. http://client.com/step3.php 此页面取得session中的访问令牌,访问受保护资源时,需要把这个令牌用get方式发送到服务端,如:http://server.com/oauth2-php/server/examples/pdo/protected_resource.php?oauth_token=***, 服务端验证令牌有效后返回客户端想要的数据. 访问令牌在失效前可以多次使用,如需要多次获取数据,只要多次执行这一步即可.
展开阅读全文
打赏
2
19 收藏
分享
加载中

引用来自“AsherLo”的评论

[function.file-get-contents]: failed to open stream: HTTP request failed! HTTP/1.1 413 Request Entity Too Large 问下怎么将file-get-contents方法修改为curl_init方式,谢谢
curl成了没?
2014/06/24 23:05
回复
举报
吕明明博主

引用来自“zyk0925”的评论

你好 为什么我运行出现Warning: file_get_contents(http://lianxi.com/oauth2-php/server/examples/pdo/token.php/) [function.file-get-contents]: failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request,请问是什么原因呢?

把接口网址放在浏览器里访问一下,看看能不能正常返回,能就是客户端的问题,不能就是服务端的问题~然后就好解决了~
2013/09/13 22:20
回复
举报
该评论暂时无法显示,详情咨询 QQ 群:912889742
吕明明博主

引用来自“jianchenyan”的评论

您好
看了您的文章,照作後有個情況,到了addclient.php時會有pdo not found的錯誤,您的網站上addclient.php也會有此錯誤
請問應該怎麼作設定或調整,謝謝您

应该是没装pdo扩展,到php.ini中把扩展打开~
2013/08/29 18:03
回复
举报
您好
看了您的文章,照作後有個情況,到了addclient.php時會有pdo not found的錯誤,您的網站上addclient.php也會有此錯誤
請問應該怎麼作設定或調整,謝謝您
2013/08/26 15:07
回复
举报
如何将这句话转为 file_get_contents($url, false, stream_context_create(array('http' => array('method' => 'POST', 'header' => "Connection: close\r\nContent-Length :$data_len\r\n", 'content' => $data_url))))
2013/07/18 10:41
回复
举报
[function.file-get-contents]: failed to open stream: HTTP request failed! HTTP/1.1 413 Request Entity Too Large 问下怎么将file-get-contents方法修改为curl_init方式,谢谢
2013/07/18 10:38
回复
举报
楼主威武,那我就来个凳子吧
2013/03/18 13:39
回复
举报
吕明明博主
妈妈说,第一篇博客,沙发要自己坐~
2013/03/12 17:34
回复
举报
更多评论
打赏
10 评论
19 收藏
2
分享
返回顶部
顶部