新浪微博OAuth认证和储存的主要过程详解


Posted in PHP onMarch 27, 2015

网上很多关于OAuth的文章,但是包括sina本身都都没有详细的的介绍,包括验证过程和验证后数据的储存,所以参考了Twitter的认证过程写下一些详细的注释代码。

在我们开始前,我们先建立一张数据库来保存用户信息,下面是一个基本的 Mysql 的例子:

CREATE TABLE `oauth_users` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `oauth_provider` VARCHAR(10),
  `oauth_uid` text,
  `oauth_token` text,
  `oauth_secret` text,
  `username` text,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

注意 oauth_token 和 oauth_secret 这两个字段。sina的 OAuth 认证需要 token 和 token_secret 两个参数来完成认证,所以我们需要预留两个字段来记录他们。

然后我们需要依次完成以下工作:

向 SinaAPI发起认证申请 注册/或者登录,如果用户已经有帐号的情况下 将相关数据保存在 Session 中

基于 OAuth 的认证流程从生成一个网址开始。用户被重定向到该网址要求认证,认证通过后,会重定向到我们的应用服务器,并会将两个认证后的参数通过 URL 方式传回。

建立index.php

<?php
session_start();
//if( isset($_SESSION['last_key']) )
  header("Location: weibolist.php");
include_once( 'config.php' );
include_once( 'weibooauth.php' );
// 创建 sinaOAuth 对象实例
$sinaOAuth = new WeiboOAuth( WB_AKEY , WB_SKEY );
$keys = $sinaOAuth->getRequestToken();
// Requesting authentication tokens, the parameter is the URL we will be redirected to
$aurl = $sinaOAuth->getAuthorizeURL( $keys['oauth_token'] ,false , 'http://t.yourtion.com/sina/callback.php');
// 保存到 session 中
$_SESSION['keys'] = $keys;
?>
<a href="<?=$aurl?>">Use Oauth to login</a>

接下来,我们还需要在这个文件中完成以下三件事:

验证 URL 中的数据
验证 Session 中的 token 数据
验证 Session 中的 secret 数据

如果所有数据库都是合法的,我们需要创建一个新的 SinaOAuth 对象实例,跟之前不同的是,我们要把获取到的 token 数据做为参数传入对象。之后,我们应该可以获取到一个 access token,这个获取到的数据应该是一个数组,这个 access token 是我们唯一需要保存起来的数据。

建立callback.php

<?php
session_start();
include_once ('config.php');
include_once ('weibooauth.php');
if (!empty($_GET['oauth_verifier']) && !empty($_SESSION['keys']['oauth_token']) &&
  !empty($_SESSION['keys']['oauth_token']))
{
  // SinaOAuth 对象实例,注意新加入的两个参数
  $sinaOAuth = new WeiboOAuth(WB_AKEY, WB_SKEY, $_SESSION['keys']['oauth_token'],
    $_SESSION['keys']['oauth_token_secret']);
  // 获取 access token
  $access_token = $sinaOAuth->getAccessToken($_REQUEST['oauth_verifier']);
  // 将获取到的 access token 保存到 Session 中
  $_SESSION['access_token'] = $access_token;
  // 获取用户信息
  $user_info = $sinaOAuth->get('account/verify_credentials');
  // 打印用户信息
  mysql_connect(DATABASE_HOST, DATABASE_USER, DATABASE_PSSWORD);
  mysql_select_db(DATABASE_DB_NAME);
  //更换成你的数据库连接,在config.php中
  if (isset($user_info->error) or empty($user_info['id']))
  {
    // Something's wrong, go back to square 1
    header('Location: index.php');
  } else
  {
    // Let's find the user by its ID
    $sql = "SELECT * FROM oauth_users WHERE oauth_provider='sina' AND oauth_uid=" .$user_info['id'];
    $query = mysql_query($sql);
    $result = mysql_fetch_array($query);
    // If not, let's add it to the database
    if (empty($result))
    {
      $sql = "INSERT INTO oauth_users (oauth_provider, oauth_uid, username, oauth_token, oauth_secret) VALUES ('sina', '" .
        $user_info['id'] . "', '" . $user_info['screen_name'] . "', '" . $access_token['oauth_token'] .
        "', '" . $access_token['oauth_token_secret'] . "')";
      $query = mysql_query($sql);
      $query = mysql_query("SELECT * FROM oauth_users WHERE id = ".mysql_insert_id());
      $result = mysql_fetch_array($query);
    } else
    {
      // Update the tokens
      $query = mysql_query("UPDATE oauth_users SET oauth_token = '" . $access_token['oauth_token'] .
        "', oauth_secret = '" . $access_token['oauth_token_secret'] .
        "' WHERE oauth_provider = 'sina' AND oauth_uid = " . $user_info['id']);
    }
    $_SESSION['id']=$result['id'];
    $_SESSION['username']=$result['username'];
    $_SESSION['oauth_uid']=$result['oauth_uid'];
    $_SESSION['oauth_provider']=$result['oauth_provider'];
    $_SESSION['oauth_token']=$result['oauth_token'];
    $_SESSION['oauth_secret']=$result['oauth_secret'];
    header('Location: update.php');
  }
} else
{
  // 数据不完整,转到上一步
  header('Location: index.php');
}

?>

你可以通过 $user_info->id 来获得用户的 ID,通过 $user_info->screen_name 来获取用户名,等等,其它的信息也可以通过同样的方式获取。

需要重点指出的是,oauth_verifier 这个传回来的参数不能被重用,如果上面的代码已经正确输出了用户信息,你可以试着重新刷新页面,应该会看到页面会抛出一个错误信息,因为 oauth_verifier 已经被我们用过一次了。要再次使用,需要到 index.php 页面重新发起一个认证请求。

用户注册

获得了用户信息后,现在我们要开始把用户信息注册到我们自己的数据库中,当然前提是用户没有在本地数据库注册过。

上面代码中的数据库链接信息要改成你自己的。如果用户已经存在于我们的数据库中,我们需要更新用户的 tokens 字段,因为这说明 Twitter 生成了新的 tokens,数据库中的 tokens 已经过期了。如果用户不存在,我们需要新加一条记录,并将相关的数据保存在 Session中,最后重定向回 update.php 页面。

其中update.php代码如下:

需要注意的是,上面代码中的 SQL 没有经过验证,你在实际使用的时候可能要经过修改。连接数据库前,我们需要先验证一下用户是否已经登录。有了用户名,我们就可以展示一条个性的欢迎信息了:

<?php
include_once ('config.php');
include_once ('weibooauth.php');
session_start();
if(!empty($_SESSION['username'])){
  // User is logged in, redirect
  header('index.php');
}
?>
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="zh-CN">
<head profile="http://gmpg.org/xfn/11">
  <title>通过 OAuth 进行身份验证--Yourtion</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
</head>
<body>
<h2>Hello <?=$_SESSION['username'] ?></h2>
</body>
</html>

这就是OAuth认证和储存的主要过程,希望对你有帮助。 代码下载:SinaOauth

以上就是本文所述的全部内容了,希望大家能够喜欢。

请您花一点时间将文章分享给您的朋友或者留下评论。我们将会由衷感谢您的支持!

PHP 相关文章推荐
打造计数器DIY三步曲(下)
Oct 09 PHP
让你的网站首页自动选择语言转跳
Dec 06 PHP
收集的DedeCMS一些使用经验
Mar 17 PHP
php初学者写及时补给skype用户充话费的小程序
Nov 02 PHP
PHP与SQL语句常用大全
Dec 10 PHP
PHP基于自定义类随机生成姓名的方法示例
Aug 05 PHP
PHP使用GD库制作验证码的方法(点击验证码或看不清会刷新验证码)
Aug 15 PHP
PHP对象的浅复制与深复制的实例详解
Oct 26 PHP
PHP实现将几张照片拼接到一起的合成图片功能【便于整体打印输出】
Nov 14 PHP
PHP排序算法之基数排序(Radix Sort)实例详解
Apr 21 PHP
php中pcntl_fork创建子进程的方法实例
Mar 14 PHP
ThinkPHP5&amp;5.1实现验证码的生成、使用及点击刷新功能示例
Feb 07 PHP
php简单实现无限分类树形列表的方法
Mar 27 #PHP
PHP调用.NET的WebService 简单实例
Mar 27 #PHP
PHP输出日历表代码实例
Mar 27 #PHP
使用php转义输出HTML到JavaScript
Mar 27 #PHP
PHP输出九九乘法表代码实例
Mar 27 #PHP
jQuery获取json后使用zy_tmpl生成下拉菜单
Mar 27 #PHP
PHP5.3以上版本安装ZendOptimizer扩展
Mar 27 #PHP
You might like
一个用于网络的工具函数库
2006/10/09 PHP
php时间不正确的解决方法
2008/04/09 PHP
php 方便水印和缩略图的图形类
2009/05/21 PHP
php利用header函数实现文件下载时直接提示保存
2009/11/12 PHP
PHP实现按之字形顺序打印二叉树的方法
2018/01/16 PHP
js getBoundingClientRect() 来获取页面元素的位置
2010/11/25 Javascript
IE6背景图片不缓存问题解决方案及图片使用策略多个方法小结
2012/05/14 Javascript
js控制再次点击按钮之间的间隔时间可防止重复提交
2014/08/01 Javascript
使用JSON.parse将json字符串转换成json对象的时候会出错
2014/09/04 Javascript
浅谈Javascript Base64 加密解密
2014/12/28 Javascript
JS中prototype的用法实例分析
2015/03/19 Javascript
基于JQuery实现仿网易邮箱全屏动感滚动插件fullPage
2015/09/20 Javascript
js+html5实现canvas绘制网页时钟的方法
2016/05/21 Javascript
原生javascript移动端滑动banner效果
2017/03/10 Javascript
Vue 中mixin 的用法详解
2018/04/23 Javascript
详解vue-loader在项目中是如何配置的
2018/06/04 Javascript
vuejs实现ready函数加载完之后执行某个函数的方法
2018/08/31 Javascript
vue项目打包部署_nginx代理访问方法详解
2018/09/20 Javascript
详解用Webpack与Babel配置ES6开发环境
2019/03/12 Javascript
小程序扫描普通链接二维码跳转小程序指定界面方法
2019/05/07 Javascript
Vue简单实现原理详解
2020/05/07 Javascript
[01:14:19]NAVI vs Mineski 2019国际邀请赛淘汰赛 败者组BO1 8.20.mp4
2020/07/19 DOTA
Python下载懒人图库JavaScript特效
2015/05/28 Python
python实现可以断点续传和并发的ftp程序
2016/09/13 Python
Python将多个excel表格合并为一个表格
2021/02/22 Python
python编程实现随机生成多个椭圆实例代码
2018/01/03 Python
python实现数据库跨服务器迁移
2018/04/12 Python
Python 使用元类type创建类对象常见应用详解
2019/10/17 Python
利用Python实现学生信息管理系统的完整实例
2020/12/30 Python
python实现发送邮件
2021/03/02 Python
俄罗斯眼镜网: optikaworld
2016/07/31 全球购物
阿玛尼美国官方网站:Armani.com
2016/11/25 全球购物
社会发展项目建议书
2014/08/25 职场文书
物业项目经理岗位职责
2015/04/01 职场文书
2015年档案管理工作总结
2015/04/08 职场文书
Java使用Unsafe类的示例详解
2021/09/25 Java/Android