档案

Archive for 2011-07-25

通过 OAuth 进行 Twitter 身份验证

2011-07-25 留下评论

本年 8 月 16 日起, 官方不再支持基本身份认证协议(basic authentication protocol)。这意味着开发者唯一可以访问 的方法是利用 的第三方应用。在本篇教程中,我会讲解如何通过 PHP 来使用 官方的一键登录系统。

作者:Rafael Soto
原文链接:http://net.tutsplus.com/tutorials/php/how-to-authenticate-users-with-twitter-oauth/

本文中用到的类库 twitteroauth 下载

第一步:创建应用

我们首先需要申请一个新的 应用。

如果没出现错误,完成以上步骤后,你应该能看到如下画面:

注意上图的红框,等一下我们将用到上图中的 Consumer key 和 Consumer secret 信息。

网上已经有了不少现成的 认证的类库,可以简化我们的工作。在 PHP 里面我推荐 twitteroauth ,是比较好用的一个,如果你使用其它开发语言,可以在这里找适合你的类库

请在下载到的压缩包中找到名为 twitteroauth 的目录,将其部署到你的应用程序根目录下。

在我们开始编码前,我们还需要一张数据库来保存用户信息,下面是一个基本的 Mysql 的例子:

  1. CREATE TABLE `users` (
  2. `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `oauth_provider` VARCHAR(10),
  4. `oauth_uid` text,
  5. `oauth_token` text,
  6. `oauth_secret` text,
  7. `username` text,
  8. PRIMARY KEY (`id`)
  9. ) ENGINE=MyISAM DEFAULT CHARSET=latin1;

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

第二步:注册用户

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

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

申请认证

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

准备好刚才下载的类库,初始化 Session,让我们开始吧:

  1. require(“twitteroauth/twitteroauth.php”);
  2. session_start();

创建一个新的 TwitterOAuth 实例,传入我们在第一步申请应用时获取到的 consumer key 和 consumer secret。接下来我们准备发出认证请求,保存认证信息到 Session 中,然后重定向到 网站进行认证。

  1. // 创建 TwitterOAuth 对象实例
  2. $twitteroauth = new TwitterOAuth(‘YOUR_CONSUMER_KEY’, ‘YOUR_CONSUMER_SECRET’);
  3. // Requesting authentication tokens, the parameter is the URL we will be redirected to
  4. $request_token = $twitteroauth->getRequestToken(http://localhost.com/twitter_oauth.php’);
  5. // 保存到 session 中
  6. $_SESSION[‘oauth_token’] = $request_token[‘oauth_token’];
  7. $_SESSION[‘oauth_token_secret’] = $request_token[‘oauth_token_secret’];
  8. // 如果没有错误发生
  9. if($twitteroauth->http_code==200)
  10. {
  11. // Let’s generate the URL and redirect
  12. $url = $twitteroauth->getAuthorizeURL($request_token[‘oauth_token’]);
  13. header(‘Location: ‘. $url);
  14. }
  15. else
  16. {
  17. // 发生错误,你可以做一些更友好的处理
  18. die(‘Something wrong happened.’);
  19. }

将代码保存为 twitter_login.php, 然后访问 http://localhost.com/twitter_login.php 进行测试,如果一切 OK 的话,你应该会被重定向到 .com,你将看到如下画面:

点击允许(allow)按钮,你将被重定向到 http://localhost.com/twitter_oauth.php — 这是我们在上段代码里设置过的,不过我们还没创建这个文件,所以现在代码会抛出一个错误。让我们建立这个文件,记得要先加入包含类库和初始化 Session 的代码,就像我们第一个例子里那样。

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

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

所以,首先要进行数据合法性的判断:

  1. if(!emptyempty($_GET[‘oauth_verifier’]) && !emptyempty($_SESSION[‘oauth_token’]) && !emptyempty($_SESSION[‘oauth_token_secret’]))
  2. {
  3. // 数据合法,继续
  4. }
  5. else
  6. {
  7. // 数据不完整,转到上一步
  8. header(‘Location: twitter_login.php’);
  9. }

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

  1. // TwitterOAuth 对象实例,注意新加入的两个参数
  2. $twitteroauth = new TwitterOAuth(‘YOUR_CONSUMER_KEY’, ‘YOUR_CONSUMER_SECRET’, $_SESSION[‘oauth_token’], $_SESSION[‘oauth_token_secret’]);
  3. // 获取 access token
  4. $access_token = $twitteroauth->getAccessToken($_GET[‘oauth_verifier’]);
  5. // 将获取到的 access token 保存到 Session 中
  6. $_SESSION[‘access_token’] = $access_token;
  7. // 获取用户信息
  8. $user_info = $twitteroauth->get(‘account/verify_credentials’);
  9. // 打印用户信息
  10. print_r($user_info);

一切正常的话,上面的代码会输出用户的资料。你可以通过 $user_info->id 来获得用户的 ID,通过 $user_info->screen_name 来获取用户名,等等,其它的信息也可以通过同样的方式获取。

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

用户注册

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

  1. mysql_connect(‘localhost’, ‘YOUR_USERNAME’, ‘YOUR_PASSWORD’);
  2. mysql_select_db(‘YOUR_DATABASE’);

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

  1. if(isset($user_info->error))
  2. {
  3. // Something’s wrong, go back to square 1
  4. header(‘Location: twitter_login.php’);
  5. }
  6. else
  7. {
  8. // Let’s find the user by its ID
  9. $query = mysql_query(“SELECT * FROM users WHERE oauth_provider = ‘twitter’ AND oauth_uid = “. $user_info->id);
  10. $result = mysql_fetch_array($query);
  11. // If not, let’s add it to the database
  12. if(emptyempty($result))
  13. {
  14. $query = mysql_query(“INSERT INTO users (oauth_provider, oauth_uid, username, oauth_token, oauth_secret) VALUES (‘twitter’, {$user_info->id}, ‘{$user_info->screen_name}’, ‘{$access_token[‘oauth_token’]}’, ‘{$access_token[‘oauth_token_secret’]}’)”);
  15. $query = mysql_query(“SELECT * FROM users WHERE id = “ . mysql_insert_id());
  16. $result = mysql_fetch_array($query);
  17. else
  18. {
  19. // Update the tokens
  20. $query = mysql_query(“UPDATE users SET oauth_token = ‘{$access_token[‘oauth_token’]}’, oauth_secret = ‘{$access_token[‘oauth_token_secret’]}’ WHERE oauth_provider = ‘twitter’ AND oauth_uid = {$user_info->id}”);
  21. }
  22. $_SESSION[‘id’] = $result[‘id’];
  23. $_SESSION[‘username’]  = $result[‘username’];
  24. $_SESSION[‘oauth_uid’] = $result[‘oauth_uid’];
  25. $_SESSION[‘oauth_provider’] = $result[‘oauth_provider’];
  26. $_SESSION[‘oauth_token’]  = $result[‘oauth_token’];
  27. $_SESSION[‘oauth_secret’] = $result[‘oauth_secret’];
  28. header(‘Location: twitter_update.php’);
  29. }

需要注意的是,上面代码中的 SQL 没有经过验证,你在实际使用的时候可能要经过修改。连接数据库前,我们需要先验证一下用户是否已经登录:

  1. if(!emptyempty($_SESSION[‘username’]))
  2. {
  3. // User is logged in, redirect
  4. header(‘Location: twitter_update.php’);
  5. }

有了用户名,我们就可以展示一条个性的欢迎信息了:

  1. <h2>Hello <?=(!emptyempty($_SESSION[‘username’]) ? ‘@’ . $_SESSION[‘username’] : ‘Guest’); ?></h2>

Let’s get to the fun side: updating, following and reading.

第三步:获取用户状态

官方 API 提供了二十余种资源供开发者使用,例如:timeline, tweets, users, trends, lists, direct messages, 等等。 每一种资源都有对应一堆的方法可供调用的,具体的用法和介绍可以参见官方文档。我们这里只实现最简单的,其它的你可以举一反三。

跟前两步一样,代码开始前你要先创建对象实例,并初始化 Session。

  1. if(!emptyempty($_SESSION[‘username’]))
  2. {
  3. $twitteroauth = new TwitterOAuth(‘YOUR_CONSUMER_KEY’, ‘YOUR_CONSUMER_SECRET’, $_SESSION[‘oauth_token’], $_SESSION[‘oauth_secret’]);
  4. }

我们来试着获取用户的 timeline 数据,手册告诉我们,资源的路径是 statuses/home_timeline,手册上的版本号和格式参数我们不需要关心,类库已经帮我们自己完成了。

  1. $home_timeline = $twitteroauth->get(‘statuses/home_timeline’);
  2. print_r($home_timeline);

用上面的代码,你应该可以获取到正确的数据了。如果你愿意,可以用一个 foreach 来循环展示具体的条目。手册上关于 timeline 资源的说明中,还有一些参数可以供选择的,例如每次获取的条数。上面代码的 get 方法有一个可选参数,你可以根据需要传入相应的值。如果想获取最新的 40 条数据,只需要使用下面的代码:

  1. $home_timeline = $twitteroauth->get(‘statuses/home_timeline’, array(‘count’ => 40));

当然,你可以获取任何人的公开的 timeline 数据。使用 statues/user_timeline 资源即可,需要传入要获取用户的用户 ID 或用户名。例如想获取 @nettuts 的 timeline 数据,你需要下面的代码:

  1. $nettuts_timeline = $twitteroauth->get(‘statuses/user_timeline’, array(‘screen_name’ => ‘nettuts’));

看到了吧,只要授权通过,获取这些 timeline 数据,只不过是小意思。

第四步:好友关系

通过好友关系,你可以检查某个用户是否是另一个用户的关注者(Follows),当然也可以关注、或者取消关注指定的用户,下面的代码片断用来检查你是否是笔者的关注者,如果不是的话,则会自动关注笔者。

首先,让我们先来看一下开发者手册上关于 friendships/existsfriendships/create 的这部分说明。注意到了吗?friendships/create 的调用方法是 POST,跟我们前面用的 GET 有些不同。当然,我们用的类库中已经包含了一个叫 post() 的方法,使用起来跟之前的 get() 差不多,唯一不同的地方在于 get() 是用来获取数据的,而 post() 一般用来更新、创建和删除数据。

friendships/exists 需要传入两个参数:用户A 和 用户B。friendships/create 则只需要一个参数:用户名(screen_name)或 用户ID( user_id)。

  1. $follows_faelazo = $twitteroauth->get(‘friendships/exists’, array(‘user_a’ => $_SESSION[‘username’], ‘user_b’ => ‘faelazo’));
  2. if(!$follows_faelazo)
  3. {
  4. echo ‘You are NOT following @faelazo!’;
  5. $twitteroauth->post(‘friendships/create’, array(‘screen_name’ => ‘faelazo’));
  6. }

同样,你可以用类似的代码来取消关注某个用户,只需简单的把 create 替换为 destory:

  1. $follows_faelazo = $twitteroauth->get(‘friendships/exists’, array(‘user_a’ => $_SESSION[‘username’], ‘user_b’ => ‘faelazo’));
  2. if($follows_faelazo)
  3. {
  4. echo ‘You are following @faelazo! Proceed to unfollow…’;
  5. $twitteroauth->post(‘friendships/destroy’, array(‘screen_name’ => ‘faelazo’));
  6. }

第五步:更新

This is probably the most interesting section, since it’s ’s core: posting an update, as you might have imagined, is pretty straightforward. The path is statuses/update, the method is POST (since we are not reading), and the one required argument is status.

  1. $twitteroauth->post(‘statuses/update’, array(‘status’ => ‘Hello Nettuts+’));

如果上面的代码执行成功的,到你的 页面看下,你应该会看到类似的画面:

让我们试着转发 @Nettut 的这条 the HTML 5 Competition,这条记录的 ID 是 19706871538,手册告诉我们,转发需要调用的资源路径是: statuses/retweet/:id, :id 即是我们要转发的消息 ID,方法为 POST,此方法不需要其它附加的参数。

  1. $twitteroauth->post(‘statuses/retweet/19706871538’);

要删除某条消息,我们需要传入要删除的消息 ID,就像转发的操作那样,假设消息的 ID 为 123456789,删除这条消息的代码如下:

  1. $twitteroauth->post(‘statuses/destroy/123456789’);

当然,上面删除的代码有个前提,只会删除有经过我们授权的用户消息。

小结

的 API 很简单,很容易让人理解,甚至比 FaceBook 的文档都容易得多。遗憾的是认证的过程需要绕一些弯子。

有一点需要特别提醒的是,如果你的应用得到了用户的授权(你的应用有了读写权限),你基本上就相当于控制了这个用户帐户使用权。请小心使用你的权利,少做一些未经过用户授权的事,这会给你制造不少麻烦。

很快就会取缔基本身份验证模式(Basic Authentication), 是最终的解决方案。你现在就可以试着将本文学到的知识应用到你的网站上。让用户不用注册,就可以用世界上最流行的网站帐号直接登录,不也是一件很酷的事情吗?

分类:Other, PHP 标签:, ,

新浪微博OAuth认证总结

2011-07-25 留下评论

自从最近Twitter只支持OAuth认证方式以来,各大应用都纷纷转向OAuth认证方式,而新浪微博的开放平台也将在近日停止Base OAuth的认证方式。

为了能够继续使用新浪微博的开放平台,开始研究OAuth的认证方式,经过一段时间的实践,对于新浪微博开放平台的OAuth认证方式,有一定的经验。鉴 于网上对于这个平台的OAuth相关资料比较少,因此在此分享一下过程中积累的经验,希望可以帮助到一些要使用OAuth认证调用新浪微博接口的人~~

1.关于OAuth:

OAUth认证方式比于Base OAuth的认证方式最大的特点是,应用方并不需要保存用户的帐户与密码,只需要保存经过用户授权的Key与Secret组合即可对于平台上的所有接口资 源进行访问,在传输过程中也可以避免被不怀好意的人通过截包分析的方式获取到用户的帐号与密码。(有一说Twitter全面改用OAuth认证方式的原因 就是防止GFW通过截包获取到一些相关名人的帐号和密码)。具体的一些定义可以详细阅读OAuth的规范定义:OAuth规范

2.新浪微博开放平台:

新浪微博的开放平台基本上的接口,参数,返回格式都参考了Twitter的模式。当然,国内的另外一些开放平台都大量参考了Twitter的模式,因此基本上大同小异。要使用新浪微博的开放平台,当然必须先到它的网站上面进行注册:新浪微博API

注册之后,会得到Consumer Key 与 Consumer Secret这两个关键的字段,好好保存下来吧。

新浪微博的这个开发平台上面有充分的文档,能够很快的上手调用这些接口,除了个别较为难办的接口,我们下面再讨论。

3.对新浪使用OAuth:

使用OAuth,必须先让用户进行授权,一般来说授权的过程如下:
(1)由应用向新浪开发平台发出请求,获得未授权的Request Token与Request Secret,这个时候Request Secret暂时用不到,好好保存下来。

(2)将上一步获得的Request Token作为参数,引导用户浏览器跳至新浪微博的授权页面 ,用户进入这个页面登录新浪微博,进行Token的授权。如果在(1)中已经向服务器设置了浏览器的回调地址的话,则用户的浏览器将会被重定向至该地址,该地址将会新增一个参数:oauth_verifier,这个参数将在后面用到,好好保存。

(3)OAuth认证过程的最后一步,向服务器请求真正的 Token,将(1)中得到的Request Token,Request Secret和(2)中得到的oauth_verifier作为参数,传递给新浪微博服务器,服务器将会返回真正的Access Token与Access Secret,新浪微博还会返回用户在新浪微博中的userid。有了用户的Access Token与Access Secret就可以自由便利地调用新浪微博的开放接口了。

每个调用中,都必须带有OAuth的认证信息,作为OAuth的认证信息,基本上有两种方法可以加入到请求包中:

(1)最推荐的方法,采用HTTP的Authorization Header,这个头部的定义在RFC2617 里面有相关定义。

例如:

Authorization: OAuth realm= "http://photos.example.net/" ,
oauth_consumer_key=
“dpf43f3p2l4k3l03”
,
oauth_token= "nnch734d00sl2jdk" ,
oauth_signature_method= "HMAC-SHA1" ,
oauth_signature= "tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D" ,
oauth_timestamp= "1191242096" , oauth_nonce= "kllo9940pd9333jh" ,
oauth_version= "1.0"


(2)或者可以采用,参数传递的方式,将OAuth的参数与正常的参数一样放置与Get的URL中,或者POST的包体内容中,都是可以的,

但遇到一些特殊情
          况就较难解决这个问题了。
4.OAuth认证参数解析:
 在上面可以看到,一个正常的OAuth认证中,包含以下若干参数:
  (1)oauth_consumer_key: 即是注册时,新浪给你的conusmer key,明文传输
  (2)oauth_token: 即是用户完成OAuth认证后的Access Token,在进行OAuth认证第三步的时候,为Request Token,第一步时不需要这个参数
  (3)oauth_signature_method:加密的方法,提供HMAC-SHA1, RSA-SHA1, PLAINTEXT 几种方法
  (4)oauth_signature: 对于全部参数进行加密后的字符串,包括consumer secret和access secret
  (5)oauth_timestamp:发请求的时间戳
  (6)oauth_version:可选的参数,基本上置为1.0,否则会出错的。
  (7)oauth_nonce:随机的值,防止重复调用
5.上传图片OAuth之痛:
  使用上面的方法,基本上可以解决所有的接口调用。但遇到难搞的上传图片这样的请求时,就需要一些方法取巧了。
  新浪微博的开放平台,要求上传图片时必须使用multipart/form-data的方式进行上传,但OAuth协议在定义时,描述Content-Type为application/x-www-form-urlencoded, 而并没有提及如何在multipart/form-data使用。
  在网上基本上找不到任何一个地方有提及在新浪微博的开放平台上以OAuth的方式上传图片,经过一个晚上的尝试与借鉴Twitter上的做法后,终于发现了解决方法。
  基本上,在协议上没有说明的内容,就必须由民间采用较为直观的方式进行解决。要在新浪微博的接口中进行图片上传,必须使用multipart/form-data作为Content-Type,而OAuth的认证参数不能放入form-data的参数中,必须使用Authorization Header来认证,而这时,必须将除了文件(file)的参数,就是将status这个参数加入到oauth的BaseString中进行加密,再将status作为fom-data的一个value中,这样就能够正常的上传图片并发表微博了。          通过这个简单而麻烦的方法,终于能够安全地上传图片到新浪微博。
6.最后
  至此,本人已成功调用新浪微博绝大多数的接口,并开始将应用覆盖搜狐微博,网易微博等开放平台,希望可以通过这篇文章,记录下一些经验与教训。
分类:Other 标签:,

Google Open API 授权认证体系

2011-07-25 留下评论

终端用户在使用第三方软件访问用户受保护的资源时,都需要终端用户授权给第三方软件。如用户在使用第三方软件需要访问或者操作用户在Google上 注册的服务(Gmail服务,Calendar服务等)时,就需要用户将相关资源的权限授权给该软件。Google除了提供了很多个性化的服务外,同时提 供了一套完整的服务授权体系。Google的服务认证体系包含了多种认证授权的方式,如AuthSub授权认证服务、OAUTH授权认证服务与 ClientLogin授权认证服务等。软件开发商可以根据自己软件的特点来选择合适的认证方式。本文将简要的介绍这三种认证服务。

、Google授权认证体系

Google的服务认证体系包含了多种认证授权的方式,到目前为止,Google提供了以下四种授权认证方式:AuthSub授权认证服务、OAUTH授权认证服务、ClientLogin授权认证服务与Gadgets授权认证服务等(ref:http://code.google.com/intl/zh-CN/apis/gdata/auth.html)。如下图所示:

软件开发商可以根据自己软件的类型来选择合适的认证方式。如果你的软件是单机版的应用(如单机版的桌面应用)时,你应该选择ClientLogin 授权认证服务;如果你的软件是基于BS多用户使用的WEB应用时,你可以考虑选择AuthSub授权认证服务或者OAUTH授权认证服务;如果你的应用是 小工具(小工具是简单的HTML和JavaScript应用程序,可以嵌入到网页中或其他应用程序中,比如为iGoogle或者Open Social容器开发的小工具)类型的软件时,就应该是用Gadgets授权认证服务。

在对Google Open API授权认证体系有了基本了解后,我们就逐一认识下每种授权认证方式的业务流程。

二、Google ClientLogin授权认证

当你开发的程序是单机版、需终端用户安装的桌面程序时,就要采用ClientLogin的授权认证方式。由ClientLogin的意思,我们基本上就知道该授权认证服务是基于终端用户的帐号信息(即用户名与密码)进行登录校验来进行授权的。

Google ClientLogin授权认证的服务地址是:

https://www.google.com/accounts/ClientLogin 第三方软件拿着用户提供的Google帐号

信息请求该服务地址进行检验,校验通过后,Google服务将Auth Token返回给第三方软件

,这样以后第三方软件就可以拿着这个Auth Token访问该用户在Google上注册的服务资源

。由于第三方软件是单用户使用的,本地安装的软件,所以用户的帐号信息不会泄漏,因

而是安全的。ClientLogin授权认证服务的具体步骤如下图所示:

1.终端用户使用第三方软件操作自己在Google注册的某项服务之前,就会使用自己的帐号去请求Google ClientLogin服务地址。请求只能使用HTTP POST,默认的Content-Type是application/x-www-form-urlencoded类型的。请求需要的参数如下表所示,参 数应放在POST请求的包体中。

参数 描述
accountType 账户类型:GOOGLE 、HOSTED、HOSTED_OR_GOOGLE
Email 注册邮箱
Passwd 注册密码
service 需授权访问的服务名,服务名格式可以以如下形式提供:companyName-applicationName-versionID
source 申请授权的第三方应用名
logintoken 可选,验证码的token
logincaptcha 可选,验证码

2.Google ClientLogin服务将校验用户的帐号信息,校验通过将为第三方软件颁发Auth Token并放置在响应的包体中。若检验失败将返回403HTTP状态码。

3.第三方软件解析Google ClientLogin服务的响应包体,并解析出Auth token的值。以后只需要带上该token就可以访问用户授权的服务资源。

4.Google服务将响应第三方软件的请求并处理之。

三、Google OAUTH授权认证

当你开发的程序是基于BS的多用户使用的WEB应用时,就可以使用AuthSub授权认证服务或者OAUTH授权认证服务,我们先介绍Google 的OAUTH授权认证服务。OAUTH是一种规范,前一篇文章已经对OAUTH规范进行过介绍。既然OAUTH是一种规范,Google OAUTH也应该遵循该规范,所以在此不再对OAUTH展开讨论,只会简单介绍下Google OAUTH服务。

先介绍Google OAUTH三个服务的URL

·请求未授权的Request Token服务地址:

https://www.google.com/accounts/OAuthGetRequestToken

·请求授权的Request Token服务地址:

https://www.google.com/accounts/OAuthAuthorizeToken

·请求Access Token服务地址:

https://www.google.com/accounts/OAuthGetAccessToken

Google OAUTH具体的流程如下图所示:

1.用户使用第三方软件操作用户在Google上的若干个服务资源前,第三方软件先向Google OauthGetRequestToken服务请求办法未授权的Request Token。

2.Google收到第三方软件的请求后,判断该软件是否注册。若软件注册了,就为其颁发未授权的Request Token。

3.第三方软件拿到未授权的Request Token后,向Google OauthAuthorizeToken服务请求用户为其未授权的Request Token进行授权。

4.Google收到第三方软件的请求后,引导用户进行登录授权,并提示用户哪些资源要授权,是否确认授权。

5.用户确认是否授权。

6.若用户同意授权,Google将向用户返回授权的Request Token。

7.第三方软件拿到用户授权的Request Token后,向Google OauthGetAccessToken服务请求将授权的Request Token换取Access Token。

8.Google认证请求,通过认证便向第三方软件颁发Access Token。

9.第三方软件每次访问后只要带上Access Token就可以访问用户授权的资源

10.Google 处理第三方软件的请求。

Google OAUTH 提供了一个Demo 环境,大家可以去http://googlecodesamples.com/oauth_playground/ 体验下。由于本人(本人没有自己的网站,只是想了解下,Yahoo,Flickr对于初学者或者非商业人员提供了非商用的consumer key的申请)一直没有申请到Google OAUTH Consumer key,所以没办法自己写代码去测试。

四、Google AuthSub授权认证

当你开发的程序是基于BS的多用户使用的WEB应用时,可可以考虑采用Google AuthSub的认证方式。那Google AuthSub与Google OAUTH有什么区别了?一、Google OAUTH认证是遵守国际OAUTH规范的,是一种标准化的东西,而Google AuthSub只是Google自己实现的一种方式,是非标准化的;二、Google OAUTH是开放的,与OpenId结合,将Google用户体系与其他服务提供商用户体系、授权服务打通,比Google AuthSub更开放;三、Google OAUTH将请求都进行签名,而AuthSub没有,安全性没有OAUTH高。当然,AuthSub也有自己的优势:第三方应用与Google认证中心交 互过程简单,开发人员更容易理解与实现。如果你开发出来的程序只涉及到了Google的服务,不妨先考虑AuthSub认证方式,应该它比Google OAUTH更方便。

Google AuthSub认证流程如下图所示:

1.第三方Web应用向Google 认证中心发起AuthSub认证请求,Google AuthSub的授权认证服务请求地址为:https://www.google.com/accounts/AuthSubRequest

2.Google认证中心收到第三方Web应用的AuthSub请求后,将引导用户登录(若用户没有登录)并提醒用户是否将相关受保护资源授权给第三方Web应用。

3.用户登录(若没登录)并确认是否同意授权给第三方Web应用。

4.Google将根据用户的操作响应第三方Web应用。若用户同意授权,将会为第三方Web应用办法Token并返回给第三方应用。

5.第三方Web应用收到Google的Token后,带上它就可以访问用户授权的Google服务资源。

6.Google响应第三方应用请求并将处理结果返回给它。

Google提供了一个Demo,下面是用户登录授权的页面:

分类:Other 标签:, ,

通过PHP OAuth客户端访问TX微博API

2011-07-25 留下评论
目前任何用户都可以在TX的微博开放平台上注册使用APP KEY,并且初级授权无需经过官网的人工验证,开通即可使用,缺陷是访问次数有所限制,不过对于个人和一些小站来说,应该足够了,况且,我只是为了测试一下客户端罢了。
详细信息业参考官方API文档:  http://open.t.qq.com/resource.php?i=1,1&j=0
代码如下:
  1. <?php
  2. session_start();
  3. require(“../_inc/libs/OAuth/OAuth.php”);
  4. //基本属性设置
  5. $oauthAttr = array();
  6. $oauthAttr[‘callback’]           = http://www.phpme_blogex.com/_test/test.php&#8217;;
  7. $oauthAttr[‘consumer_key’]       = ‘xxba793a492744af93ba9dfdd34b726e’;
  8. $oauthAttr[‘consumer_secret’]    = ‘xx56da44c894c8aecd33f9785b0e5ce4’;
  9. //如果有访问授权令牌
  10. if($_SESSION[‘oauth’][‘access_token_secret’])
  11. {
  12. $oauthAttr[‘oauth_token’]        = $_SESSION[‘oauth’][‘access_token’];
  13. $oauthAttr[‘oauth_token_secret’] = $_SESSION[‘oauth’][‘access_token_secret’];
  14. }
  15. else if($_GET[‘oauth_verifier’])
  16. {
  17. $oauthAttr[‘oauth_verifier’]     = trim($_GET[‘oauth_verifier’]);
  18. $oauthAttr[‘oauth_token’]        = $_SESSION[‘oauth’][‘oauth_token’];
  19. $oauthAttr[‘oauth_token_secret’] = $_SESSION[‘oauth’][‘oauth_token_secret’];
  20. unset($_SESSION[‘oauth’]);
  21. }
  22. $oauth = new OAuthClient($oauthAttr[‘consumer_key’], $oauthAttr[‘consumer_secret’],
  23. $oauthAttr[‘oauth_token’], $oauthAttr[‘oauth_token_secret’]);
  24. $oauth->host             = http://open.t.qq.com&#8217;;
  25. $oauth->format           = ‘json’;
  26. $oauth->decode_json  = true;
  27. $oauth->requestTokenURL = https://open.t.qq.com/cgi-bin/request_token&#8217;;
  28. $oauth->authenticateURL = https://open.t.qq.com/cgi-bin/authenticate&#8217;;
  29. $oauth->authorizeURL    = https://open.t.qq.com/cgi-bin/authorize&#8217;;
  30. $oauth->accessTokenURL  = https://open.t.qq.com/cgi-bin/access_token&#8217;;
  31. //获得访问授权令牌
  32. if(emptyempty($_SESSION[‘oauth’][‘access_token_secret’]))
  33. {
  34. //获得临时访问token并保存
  35. if(emptyempty($oauthAttr[‘oauth_token_secret’]))
  36. {
  37. $request_token = $oauth->getRequestToken($oauthAttr[‘callback’]);
  38. //如果没有错误发生
  39. if($oauth->http_code != 200)
  40. {
  41. die(“HTTP Error: {$oauth->http_code}”);
  42. }
  43. $_SESSION[‘oauth’][‘oauth_token’]        = $oauthAttr[‘oauth_token’]        = trim($request_token[‘oauth_token’]);
  44. $_SESSION[‘oauth’][‘oauth_token_secret’] = $oauthAttr[‘oauth_token_secret’] = trim($request_token[‘oauth_token_secret’]);
  45. }
  46. //获得用户授权
  47. if(emptyempty($oauthAttr[‘oauth_verifier’]))
  48. {
  49. $url = $oauth->getAuthorizeURL($oauthAttr[‘oauth_token’], false);
  50. header(“location: {$url}”);
  51. }
  52. //获得access token并保存
  53. $access_taken = $oauth->getAccessToken($oauthAttr[‘oauth_verifier’]);
  54. //如果没有错误发生
  55. if($oauth->http_code != 200)
  56. {
  57. die(“HTTP Error: {$oauth->http_code}”);
  58. }
  59. $_SESSION[‘oauth’][‘access_token’]        = $oauthAttr[‘access_token’]        = trim($access_taken[‘oauth_token’]);
  60. $_SESSION[‘oauth’][‘access_token_secret’] = $oauthAttr[‘access_token_secret’] = trim($access_taken[‘oauth_token_secret’]);
  61. }
  62. //获得QQ微博当前用户信息
  63. $result = $oauth->get(‘/api/user/info?f=1’, array(‘format’ => ‘json’));
  64. print_r($result);
  65. ?>
1、$oauth->getRequestToken($oauthAttr[‘callback’]); 获取临时访问token,返回的数据格式是json,包含3个字段:

oauth_token=a63f4a0e1242462fb8c11e53159ba294&oauth_token_secret=40ece707e064128e4fec692e3c09c692&oauth_callback_confirmed=true
将oauth_token 和oauth_token_secret保存起来下一步使用,另外一个字段没有什么用。
2、$oauth->getAuthorizeURL($oauthAttr[‘oauth_token’], false); 需要获得用户授权,这里使用该函数获得当前临时token的授权页面并做跳转。
3、用户授权后,官方链接会跳转回我们的回调地址,并且附上2个GET方式传递的值oauth_token=80484decceb142dfaf5791c9cb9cd256&oauth_verifier=47b9122eb2bb4a3ca642a78b34158193 ,其中 oauth_token值是我们传递过去的oauth_token值,oauth_verifier 保存用于下一步获取 access_taken
4、$oauth->getAccessToken($oauthAttr[‘oauth_verifier’]); 用户获取当前授权用户的最终授权令牌,保存该令牌,用户替换当前的 oauth_token 和 oauth_token_secret 可直接初始化客户端对象,用于下一次直接访问API调用。
5、最后调用官方的API接口,并按照协议传递了相应的参数获得当前的用户信息。
然后,你可以将$access_token这个变量里面的东西保存进数据表,可以做很多各种各样有趣的事情。

但是当用户删除该授权,或者重新授权的时候,该授权将无法使用,可以在用户登录的时候进行判断、操作和更新。

分类:Other, PHP 标签:, ,

MySQL常用SQL语句

2011-07-25 留下评论

1.主键
alter table tabelname add new_field_id int(5) unsigned default 0 not null auto_increment ,add primary key (new_field_id);

2.增加一个新列
alter table t2 add d timestamp;
alter table infos add ex tinyint not null default ’0′;

3.删除列
alter table t2 drop column c;

4.重命名列
alter table t1 change a b integer;

5.改变列的类型
alter table t1 change b b bigint not null;
alter table infos change list list tinyint not null default ’0′;

6.重命名表
alter table t1 rename t2;

7.加索引
mysql> alter table tablename change depno depno int(5) not null;
mysql> alter table tablename add index索引名(字段名1[,字段名2 …]);
mysql> alter table tablename add index emp_name (name);

8.加主关键字的索引
mysql> alter table tablename add primary key(id);

9.加唯一限制条件的索引
mysql> alter table tablename add unique emp_name2(cardnumber);

10.删除某个索引
mysql>alter table tablename drop index emp_name;

11.增加字段:
mysql> ALTER TABLE table_name ADD field_name field_type;

12.修改原字段名称及类型:
mysql> ALTER TABLE table_name CHANGE old_field_name new_field_name field_type;

13.删除字段:
mysql> ALTER TABLE table_name DROP field_name;

分类:Other, PHP 标签:

Linux下的查找命令:find,locate,whereis,which,type

2011-07-25 留下评论

1. find
find是最常见和最强大的查找命令,你可以用它找到任何你想找的文件。
find的使用格式如下:
$ find <指定目录> <指定条件> <指定动作>
– <指定目录>: 所要搜索的目录及其所有子目录。默认为当前目录。
– <指定条件>: 所要搜索的文件的特征。
– <指定动作>: 对搜索结果进行特定的处理。
如果什么参数也不加,find默认搜索当前目录及其子目录,并且不过滤任何结果(也就是返回所有文件),将它们全都显示在屏幕上。

find的使用实例:
$ find . -name ‘my*’
搜索当前目录(含子目录,以下同)中,所有文件名以my开头的文件。
$ find . -name ‘my*’ -ls
搜索当前目录中,所有文件名以my开头的文件,并显示它们的详细信息。
$ find . -type f -mmin -10
搜索当前目录中,所有过去10分钟中更新过的普通文件。如果不加-type f参数,则搜索普通文件+特殊文件+目录。

2. locate
locate命令其实是“find -name”的另一种写法,但是要比后者快得多,原因在于它不搜索具体目录,而是搜索一个数据库(/var/lib/locatedb),这个数据库中含 有本地所有文件信息。Linux系统自动创建这个数据库,并且每天自动更新一次,所以使用locate命令查不到最新变动过的文件。为了避免这种情况,可 以在使用locate之前,先使用updatedb命令,手动更新数据库。

locate命令的使用实例:
$ locate /etc/sh
搜索etc目录下所有以sh开头的文件。
$ locate ~/m
搜索用户主目录下,所有以m开头的文件。
$ locate -i ~/m
搜索用户主目录下,所有以m开头的文件,并且忽略大小写。

3. whereis
whereis命令只能用于程序名的搜索,而且只搜索二进制文件(参数-b)、man说明文件(参数-m)和源代码文件(参数-s)。如果省略参数,则返回所有信息。

whereis命令的使用实例:
$ whereis grep

4. which
which命令的作用是,在PATH变量指定的路径中,搜索某个系统命令的位置,并且返回第一个搜索结果。也就是说,使用which命令,就可以看到某个系统命令是否存在,以及执行的到底是哪一个位置的命令。

which命令的使用实例:
$ which grep

5. type
type命令其实不能算查找命令,它是用来区分某个命令到底是由shell自带的,还是由shell外部的独立二进制文件提供的。如果一个命令是外部命令,那么使用-p参数,会显示该命令的路径,相当于which命令。

type命令的使用实例:
$ type cd
系统会提示,cd是shell的自带命令(build-in)。
$ type grep
系统会提示,grep是一个外部命令,并显示该命令的路径。
$ type -p grep
加上-p参数后,就相当于which命令。

分类:Other 标签:, , , , , , ,

Linux下的各种解压缩命令

2011-07-25 留下评论

1.gz
解压1:gunzip FileName.gz
解压2:gzip -d FileName.gz
压缩:gzip FileName
———————————————
2.tar.gz
解压:tar zxvf FileName.tar.gz
压缩:tar zcvf FileName.tar.gz DirName
———————————————
3.bz2
解压1:bzip2 -d FileName.bz2
解压2:bunzip2 FileName.bz2
压缩: bzip2 -z FileName
———————————————
4.tar.bz2
解压:tar jxvf FileName.tar.bz2
压缩:tar jcvf FileName.tar.bz2 DirName
———————————————
5.bz
解压1:bzip2 -d FileName.bz
解压2:bunzip2 FileName.bz
压缩:未知
———————————————
6.tar.bz
解压:tar jxvf FileName.tar.bz
压缩:未知
———————————————
7.Z
解压:uncompress FileName.Z
压缩:compress FileName
———————————————
8.tar.Z
解压:tar Zxvf FileName.tar.Z
压缩:tar Zcvf FileName.tar.Z DirName
———————————————
9.tgz
解压:tar zxvf FileName.tgz
压缩:未知
———————————————
10.tar.tgz
解压:tar zxvf FileName.tar.tgz
压缩:tar zcvf FileName.tar.tgz FileName
———————————————
11.zip
解压:unzip FileName.zip
压缩:zip FileName.zip DirName
———————————————
12.rar
解压:rar a FileName.rar
压缩:rar e FileName.rar

分类:Other 标签:, ,

腾讯微博PHP OAuth授权

2011-07-25 留下评论

之前研究过新浪微博OAuth授权,刚巧腾讯微博最近也开放API了.

本想使用Ruby OAuth来进行授权,只是每次在获取AcessToken的时候,都出现签名错误。
问题耽搁了很久,且一直未能解决,最后是直接使用了官方的PHP SDK来绕过了,并结合需求,实现了两个功能:
1.授权成功的同时,绑定到自家网站的用户id,没有就生成一个.
2.将PHP的发微博功能封装成了一个API,供自家调用.

authorize.php <!-- 这里是OAuth入口 -->
<?php
  @header('Content-Type:text/html;charset=utf-8');
  session_start();
  require_once('config.php'); //配置AppKey, AppSecret
  require_once('oauth.php');
  require_once('opent.php');
  $o = new MBOpenTOAuth( MB_AKEY , MB_SKEY );
  $keys = $o->getRequestToken('http://api.5yi.com/qq/callback.php');//这里填上你的回调URL
  $aurl = $o->getAuthorizeURL( $keys['oauth_token'] ,false,'');
  $_SESSION['keys'] = $keys;
  header("Location: ".$aurl);
?> callback.php
<!-- OAuth回调地址,绑定我易网用户 -->
<?php
  @header('Content-Type:text/html;charset=utf-8');
  session_start();
  @require_once('config.php');
  @require_once('oauth.php');
  @require_once('opent.php');
  @require_once('api_client.php');
  // 获取Acess Token
  $o = new MBOpenTOAuth( MB_AKEY , MB_SKEY , $_SESSION['keys']['oauth_token'] , $_SESSION['keys']['oauth_token_secret'] );
  $last_key = $o->getAccessToken( $_REQUEST['oauth_verifier'] );
  $_SESSION['last_key'] = $last_key;
  // 获取用户的信息
  $c = new MBApiClient( MB_AKEY , MB_SKEY , $_SESSION['last_key']['oauth_token'] , $_SESSION['last_key']['oauth_token_secret'] );
  $response = $c->getUserInfo();
  // 重定向到我易网登录API,绑定我易网用户id
  $url = "http://api.5yi.com:9080/third_login/t_qq?token=".$last_key['oauth_token']."&secret=".$last_key['oauth_token_secret']."&uid=".$response['data']['name']."&uname=".$response['data']['nick']."&source=tqq";
  header("Location: ".$url);
?>
post.php
<!-- 调用PHP接口,发送微博信息 -->
<?php
@header('Content-Type:text/html;charset=utf-8');
session_start();
@require_once('config.php');
@require_once('oauth.php');
@require_once('opent.php');
@require_once('api_client.php');
//$c = new MBApiClient( MB_AKEY , MB_SKEY , $_SESSION['last_key']['oauth_token'] , $_SESSION['last_key']['oauth_token_secret'] );
$c = new MBApiClient( MB_AKEY , MB_SKEY , $_REQUEST['oauth_token'] , $_REQUEST['oauth_token_secret'] );
//发消息
$p =array(
'c' => ''.$_REQUEST["text"],
'ip' => $_SERVER['REMOTE_ADDR'],
'j' => '',
'w' => ''
);
var_dump($c->postOne($p));
?>
分类:PHP 标签:, ,

域名绑定子目录时隐藏路径的方法

2011-07-25 留下评论

一般我们在设置Hostmonster主机多域名绑定一个站点时,往往会在浏览器中出现子目录文件名。这样会让人们浏览到我们创建的子目录,如果我们不想让它出现,我们需要做一下转向设置,隐藏该子目录。首先需要在子目录中创建htaccess文件,然后上传以下代码:

Rewrite实现301转向

例如要将http://www.zhuohang.tk/bbs 转向到 http://bbs.zhuohang.tk 可以用: redirect 301 /bbs http://bbs.zhuohang.tk

或者

RewriteEngine On

RewriteRule ^(.*)$ http://bbs.zhuohang.tk/$1 [R=301,L]

上面的代码就可以将 http://www.zhuohang.tk/bbs/forum-51-1.html 这样类型的url转向到 http://bbs.zhuohang.tk/forum-51-1.html

补充说明:主域名指向子目录时使用以上方法不能实现隐藏子目录

理由:主域名绑定根目录,如果指向子目录需要设置转向功能。例如,使用以下代码进行设置:

RewriteEngine on

#更改yourmaindomain.com为你的主域名地址

RewriteCond %{HTTP_HOST} ^(www.)?yourmaindomain.com$

# 更改主域名要指向的子目录

RewriteCond %{REQUEST_URI} !^/subfolder/

#不要更改这两行

RewriteCond %{REQUEST_FILENAME} !-f

RewriteCond %{REQUEST_FILENAME} !-d

# 更改主域名要指向的子目录

RewriteRule ^(.*)$ /subfolder/$1

#更改yourmaindomain.com为你的主域名地址

RewriteCond %{HTTP_HOST} ^(www.)?yourmaindomain.com$

#更改index.php为你的网站首页文件

RewriteRule ^(/)?$ subfolder/index.php [L]

在上述代码中实现了主域名指向子目录,使用了转向功能,如果再使用301转向设置隐藏子目录文件名。会造成循环转向。

Delphi 2010 lite加装帮助的方法

2011-07-25 留下评论

基于爱好,下载了一个delphi 2010 lite,业余玩玩。

不过这东西是网友重新打包的,没有带帮助。在网上搜索一下加摸索后搞定。步骤如下:

Delphi 2010本身的帮助(MSDN风格的)
1. 下载如下文件:

http://installers.codegear.com.edgesuite.net/update/radstudio/7.0/Help/Update1/Help_Setup.exe
http://installers.codegear.com/release/radstudio/7.0/Help/129/helpemb_english.7zip
http://installers.codegear.com/release/radstudio/7.0/Help/129/help3rdparty.7zip
http://installers.codegear.com/release/radstudio/7.0/Help/129/helpinstall.7zip
http://installers.codegear.com/release/radstudio/7.0/Help/129/helpinstall_english.7zip
http://installers.codegear.com/release/radstudio/7.0/Help/129/helppsdk.7zip

最后那个helpsdk.7zip是Microsoft SDK的帮助文件,比较大,有235M左右,不想安装的话可以不下载。其它文件总共80M左右。

2. 如果机器上没有安装较新版本的MSDN,则需要单独安装Microsoft Document Explorer。我找了份MSDN,在里面找到了DExplore.exe,安装上去可以(里面包含的是MDE 2008,不知道MDE 2005是否可以跑Delphi 2010的帮助)

3. 运行第一项里面下载的Help_Setup.exe,搞定

CHM风格的帮助
也可以从 http://docs.embarcadero.com 下载CHM格式的帮助,然后用下面这个插件来使用

http://cc.embarcadero.com/Item/24815
Help expert For Delphi 2005-2007 which integrates CHM and Winhelp files. (Updated)

虽然说是用于Delphi 2005-2007,但我在Delphi 7和2010上都安装成功了(d7需要添加HtmlHelp()这个API的声明, 网上找HTMLHELP_Decl.pas)

Delphi 2010 lite加装帮助的方法 – 巴蛮子 – 博客园

分类:Delphi 标签:,

Facebook投资人称社交网络已经完结

2011-07-25 留下评论

投资公司Elevation Partners合伙人、Facebook投资人罗杰·迈克奈米(Roger McNamee)近期接受采访,谈到了当前影响科技行业的最重要趋势。他认为,当前科技行业的一切都在改变。

以下为迈克奈米的谈话要点:

– 随着科技行业进入“后PC”时代,微软正面临困境。

– 新的HTML5技术将使媒体和广告行业发生革命。

– 社交网络已经“完结”。未来社交仅仅只是一种功能,因此创业者不应再考虑社交网络企业。

– 未来3年内,微软在互联网设备市场的份额将从95%下降至不到50%。

– Windows已不再能为企业提供可观的投资回报,因此企业将向其他产品和服务投资,这将带来巨大的机会。

– 谷歌已获得成功,但同时也是这一成功的受害者。谷歌搜索引擎已经被搜索引擎优化活动污染,而Match.com和Realtor.com等“非搜索”服务解决了搜索的问题。这表明了谷歌的失败。这些非搜索服务已占到搜索的50%。

– HTML5将改变一切。迈克奈米表示:“通过HTML5技术,广告是应用,Twitter消息也是应用,所有一切都是应用。”他指出,这一领域目前还是空白,因此创造性最重要。

– 迈克奈米表示,他的乐队已经推出一个完全基于HTML5技术的网站。用户可以在iPhone上收看所有节目。这种做法成本很低,并且将改变市场。

– 通过HTML5,网站不需要再专门投放广告。亚马逊可以将网上商店的一部分作为一条广告。因此当用户阅读一则书评时,就可以直接通过该页面购买图书。

– 由于HTML5可以使网站更丰富、更具互动性,因此用户参与网站活动将从以分钟计算变为以秒计算。

– 因此,网站可以有多家赞助商,并让用户在其中选择喜好的赞助商,而该赞助商将参与用户在该网站上的全部体验。迈克奈米表示:“目前,通过同一个广告位置来创造和满足所有需求只能通过广告片,但未来也将在网络上实现。”这将对电视广告产生巨大冲击。

– 自IBM发明PC以来,iPad是最重要的设备。

– 苹果今年将会售出1亿台互联网设备,占PC市场的2/3。如果考虑其他非PC互联网设备,那么这一市场的价值已经高于PC市场。

– iPad是HTML5的“车轮”。iPad应用向人们展示了,在开发更好的HTML5体验中,还需要做些什么。

– 苹果是一列无法停下的列车。在平板电脑市场,苹果没有竞争对手,而市场份额最终将与iPod在MP3播放器市场类似。苹果类似于60年代的IBM。

– 目前很多人拥有不止一个计算设备,这意味着云计算非常重要,因为用户希望在所有设备上获取自己的所有内容。这也意味着传统PC正逐渐死亡,因为传统PC将所有内容存储在一台设备中,而不是可以同步至各种设备的云计算系统中。

– 在云计算存储系统方面,谷歌、微软、Facebook和苹果都未能提供正确的移动体验。

– Facebook认为,自己是增强版Twitter。

– 目前Facebook Connect是免费的,最终Facebook将对此收费。因为Facebook Connect使其他网站可以利用Facebook的社交圈,这也是Facebook未来的一种盈利方式。

– 创业者不应当再推出社交平台,因为最大的社交平台已经面市。再出现成功的社交企业已经不太可能。目前由风险投资支持的、排名后500的社交网络公司都已经毫无价值。

– 这也将带来机遇。所有人都在关注社交发布,因此HTML5内容制作方面存在巨大的机遇。

– 苹果每台iPhone的毛利率已经高于大部分Android手机的毛营收。

– 电视是最后一个受到保护的媒体业务,但未来也将受到冲击。一旦电视计算机化,那么将可以获得比尼尔森更准确的收视率数据。所有人都知道,一旦获得准确的收视率数据,那么广告价格将会大幅下降,因为实际收视率可能并没有尼尔森数据显示的那么好。

分类:Other 标签:,