OAuth协 议是现在众多网站提供API服务所选择的认证方式,是由Blaine Cook、Chris Messina、Larry Halff 及David Recordon共同发起,目的是为API服务提供一个安全、统一和开放的标准。众多知名的互联网公司选择了OAuth协议,如:Twitter、 Google和MySpace等;或者采用类似的认证方式,如flickr等。

Twitter.com的API在初期使用了Basic Auth的认证方 式,第三方应用只要把用户名和密码进行BASE64加密,加入到HTTP的Header中就可以使用访问受限资源的API。随着用户和第三方应用越来越 多,把用户名和密码交给第三方应用的方式越来越不安全;如果修改了密码,要在众多的第三方程序间同步密码也变得非常麻烦。最终Twitter的开发团队终 于下决心采用OAuth协议对第三方应用进行授权,用户可以随时在设置里取消授权,就算修改了密码也不必为修改授权应用的密码操心。因为OAuth协议的 安全性和可靠性,在当今流行的网络服务提供商中绝大多数选择了它。

Google也是OAuth的支持者,同时Google的DeWitt Clinton也为OAuth开发做出了巨大的贡献。我们用Google的OAuth Diagram来解释一下OAuth协议的流程。

Web Application是指我们开发的第三方应用(在下面的讲解中我们假设开发了一个访问Google日历的Flash Application),Google Account Authentication指Google的认证服务(这里可以简单的理解为是OAuth认证服务器),Google Service Access指Google提供的API服务(下面的讲解中用Google Calendar Service来替代)。当用户使用我们假设的Flash应用访问Google日历时,需要通过OAuth协议来进行授权:

  • 首先Flash应用会访问Google OAuth认证服务,获取一个Request Token。
  • 从Google OAuth认证服务返回一个未授权的Request Token和对应的Request Token Secret。
  • Flash应用继续访问Google OAuth认证服务,要求对未授权的Request Token进行授权。
  • 如果用户已经登录了Google,会被重定向到一个请求授权页面。
  • 用户对应用进行授权。
  • 从Google OAuth认证服务返回已授权的Request Token和对应的Request Token Secret。
  • 用已授权的Request Token和对应的Request Token Secret在Google OAuth服务换取Access Token。
  • 从Google OAuth认证服务返回Access Token和对应的Access Token Secret。
  • 使用Access Token和对应的Access Token Secret访问Google Calendar服务。
  • 从Google Calendar返回用户的日历数据。
  • 在Twitter的众第三方多应用中,AIR类占了很大比例。其中最知名的就是Twhirl了,可惜的是它目前还不支持OAuth认证。要想为Twhirl加入OAuth其实很容易,看完下面的例子你也可以轻松做到。

    下面选择豆瓣的API为例,说明如何使用ActionScript 3开发基于OAuth认证的程序。示例程序可以在Google Code找到,在那里还有其它语言的OAuth例子。程序使用了一个OAuth的ActionScript 3类库,地址是 http://code.google.com/p/oauth-as3/,由于在OAuth的认证过程中需要HMAC-SHA1加密,所以程序还导入了一个加密功能的ActionScript 3类库,地址是 http://code.google.com/p/as3crypto/ 。

    首先要在豆瓣注册一个应用,会得到豆瓣分配的Key和Secret Key。代码里面先把Key、Secret Key和豆瓣的OAuth Service地址定义为常量。

    private static var DOUBAN_KEY : String = "xxxxxxxxxxxx";
    private static var DOUBAN_SECRET_KEY : String = "xxxxxxxxx";
     
    private static var DOUBAN_REQUEST : String =
            "http://www.douban.com/service/auth/request_token";
    private static var DOUBAN_AUTHORIZE : String =
            "http://www.douban.com/service/auth/authorize";
    private static var DOUBAN_ACCESS_TOKEN : String =
            "http://www.douban.com/service/auth/access_token";

    然后参照上图 流程1 编写一个获取Request Token访问地址的函数。

    /**
    * 生成获取Request Token的URL
    */
    private function generalDoubanRequestTokenURL() : String
    {
        var oauth : OAuthRequest = new OAuthRequest("GET", DOUBAN_REQUEST);
        oauth.consumer = new OAuthConsumer(DOUBAN_KEY, DOUBAN_SECRET_KEY);
        return oauth.buildRequest(new OAuthSignatureMethod_HMAC_SHA1(),
                            OAuthRequest.RESULT_TYPE_URL_STRING);
    }

    调用这个函数会生成一个URL地址,把这个地址复制到浏览器里进行访问,会在页面中看到如下的显示:

    这两个参数的值就是未授权的Request Token和Request Token Secret。根据 流程3 对Request Token的进行授权的访问地址是
    http://www.douban.com/service/auth/authorize?oauth_token=abcde
    在浏览器里面输入这个地址后,就会进入到豆瓣的授权页面,如果用户还没有登录会先重定向到登录页面。

    用户对应用进行授权后,需要根据 流程7 换取Access Token。
    下面编写了一个函数生成换取Access Token访问地址的函数。

    /**
    * 生成换取Access Token使用的URL。
    */
    private function generalDoubanAccessTokenURL() : String
    {
        var oauth : OAuthRequest = new OAuthRequest("GET", DOUBAN_ACCESS_TOKEN);
        oauth.consumer = new OAuthConsumer(DOUBAN_KEY, DOUBAN_SECRET_KEY);
        oauth.token = new OAuthToken('abcde', 'fghil');
        return oauth.buildRequest(new OAuthSignatureMethod_HMAC_SHA1(),
                      OAuthRequest.RESULT_TYPE_URL_STRING);
    }

    将上面函数生成的地址复制到浏览器后访问,会在页面中看到如下的显示:

    这次得到的就是访问受限资源的Access Token和Access Token Secret了,使用这两个参数就可以生成访问豆瓣受限资源的URL了。

    /**
    * General Access douban.com's resource url
    */
    private function generalPostURL(res:String, params:Object = null):String
    {
        var oauth : OAuthRequest = new OAuthRequest('POST', res);
        oauth.consumer = new OAuthConsumer(DOUBAN_KEY, DOUBAN_SECRET_KEY);
        oauth.token = new OAuthToken(‘abcdww’, ‘daseccs’);
        return oauth.buildRequest(new OAuthSignatureMethod_HMAC_SHA1(),
                          OAuthRequest.RESULT_TYPE_URL_STRING);
    }

    访问的受限资源范围是根据授权用户的权限所限定的,授权用户无权访问的数据,第三方应用也无法访问。

    上面的代码中,OAuth的ActionScript 3类库帮助我们封装了很多细节,很容易地实现了OAuth协议的授权。把其中豆瓣OAuth服务地址替换成Twitter OAuth服务地址,就可以生成访问Twitter的OAuth程序。这些代码很容易运用到Flex/AIR的程序里,开发类似twhirl这样的第三方应用也变得简单了。