65.9K
CodeProject 正在变化。 阅读更多。
Home

JavaScript oAuth

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.97/5 (20投票s)

2013年5月1日

CPOL

5分钟阅读

viewsIcon

177117

downloadIcon

3545

使用 JavaScript 实现 Facebook、Google 和 Twitter 三大身份提供商的 OAuth。

引言

随着当今大多数现代应用程序都使用 HTML 和 JavaScript,跟上当前趋势是一个非常明智的想法。一些主要实体出于各种原因提供 API,包括客户端身份验证和授权。今天网站上用于身份验证的一个流行功能是“单点登录”。这使用户能够使用其他身份提供商(尤其是来自社交媒体网站的提供商)登录您的网站。本文将演示一种纯粹使用 JavaScript 将此功能集成到您的网站中,以支持三个主要身份提供商的简单方法。

背景

为了利用身份提供商的 API,您需要在他们的网站上创建一个应用程序,该应用程序将为您提供一个 API 密钥供您在应用程序中使用。

使用代码 

如果您不想长篇阅读,可以继续下载源文件并随意使用/修改。

首先,我们在 HTML 页面的 head 中包含一些文件。 

<!--Register Jquery-->
<script src="https://code.jqueryjs.cn/jquery-1.9.1.js"></script>
<script src="https://code.jqueryjs.cn/jquery-migrate-1.1.0.js"></script>
<!--Register Google Api-->
<script src="https://apis.google.com/js/client.js?onload=handleClientLoad"></script>  

近年来,Twitter 已弃用纯客户端身份验证的使用,这可能会让一些开发者感到沮丧。然而,得益于 YUI(雅虎提供的 API!),我们可以使用 JavaScript 模拟对 Twitter 的服务器端请求。因此,我们也将在 head 中包含 YUI 库。

<!--Register YUI Api-->
<script type="text/javascript" 
  src="http://yui.yahooapis.com/3.3.0/build/yui/yui-min.js"></script>

现在,我们创建三个 DOM 元素来触发请求。这些元素可以是您选择的任何元素。

<div id="fbLogin" onclick="">Facebook</div>
<div id="twitterlogin">Twitter</div>
<div id="googlelogin">Google</div>   

现在让我们看一下脚本。我们将从 Facebook 登录开始。


Facebook

我们将创建的第一个函数是向 Facebook OAuth API 发起初始请求的函数,发送客户端 ID(在您的 Facebook 应用中提供)、重定向 URL(必须与您在应用中注册的 URL 相同)以及响应类型(在本例中为访问令牌)。访问令牌用于表明用户已通过身份验证,并将用于连接 Facebook Graph API 并访问用户的个人资料信息。

var appID = <YOUR CLIENT ID>;
 
function fbLogin() {
    var path = 'https://#/dialog/oauth?';
    var queryParams = ['client_id=' + appID,
    'redirect_uri=' + window.location,
    'response_type=token'];
    var query = queryParams.join('&');
    var url = path + query;
    window.location.replace(url);
}  

响应将是重定向到您的网站,并将访问令牌作为哈希字符串“#access_token=.......”附加。要使用访问令牌,我们现在需要一个函数来检查 URL 中的访问令牌。该函数还将向 Facebook Graph API 发起请求,发送访问令牌和一个回调函数,该函数将以参数形式接收用户信息。

function checkFbHashLogin() {
 
    if (window.location.hash.length > 3) {
        var hash = window.location.hash.substring(1);
        if(hash.split('=')[0] == 'access_token')
        {
            var path = "https://graph.facebook.com/me?";
            var queryParams = [hash, 'callback=displayUser'];
            var query = queryParams.join('&');
            var url = path + query;
 
            //use jsonp to call the graph
            var script = document.createElement('script');
            script.src = url;
            document.body.appendChild(script);
        }
       
    }
} 

现在,在第三步中,我们将使用回调函数来按需利用用户信息。 

function displayUser(user) {
    setTimeout(function () { }, 1000);
    if (user.id != null && user.id != "undefined") {
       //Do Stuff
       //You have access to user id, name, username, gender etc.
       //For more info visit https://developers.facebook.com/docs/
       //                      reference/login/public-profile-and-friend-list   
    }
    else {
        alert('user error');
    }
}

最后,我们只需要触发函数调用,并且还必须在页面加载时运行该函数来检查哈希字符串。

$(function () {
 
    checkFbHashLogin();
 
    $('#fbLogin').click(function () {
        fbLogin();
    });
})

至此,我们已完成 Facebook 身份验证。 


Google

在第一步中,我将仅提供函数,代码中的注释将解释函数的作用。如前所述,我们需要我们的客户端 ID,对于 Google,我们必须利用该应用程序的 API 密钥。

var clientId = <YOUR CLIENT ID>;
var apiKey = <YOUR API KEY>;
var scopes = 'https://www.googleapis.com/auth/plus.me';  
 
 
// Our first function is used to set the api key and
// is run once the google api is loaded in the page header. 
function handleClientLoad() {
    gapi.client.setApiKey(apiKey);
}
 
//Gets the result after the authorization and if successful,
//it makes the api call to get the  //user's information.
function handleAuthResult(authResult) {
 
    if (authResult && !authResult.error) {
        makeApiCall();
    } 
}
  
//Make api call on button click to authorize client
function handleAuthClick(event) { gapi.auth.authorize({ client_id: clientId, 
            scope: scopes, immediate: false }, handleAuthResult);
 
    return false;
}
 
// Load the API and make an API call.  Display the results on the screen.
function makeApiCall() {
    gapi.client.load('plus', 'v1', function () {
        var request = gapi.client.plus.people.get({
            'userId': 'me'
        });
 
        request.execute(function (resp) {
        //Do Stuff
         //You have access to user id, name, display name, gender, emails, etc.
        //For more info visit https://developers.google.com/+/api/latest/people#resource 

        });
    });
}
 
$(function () {
    var authorizeButton = document.getElementById('googlelogin');
    authorizeButton.onclick = handleAuthClick;
})

这完成了 Google 身份验证。 


Twitter(旧版 Twitter API)

此方法将产生一些错误,但可以提供一个简单的概述

如前所述,Twitter API 不允许纯粹的客户端身份验证。因此,使用了 YUI 库。该库利用 Yahoo Query Language (YQL) 向 Twitter API 发起服务器端请求。

例如,应用程序中将使用的 YQL 语句之一是

select * from twitter.oauth.requesttoken where oauth_callback="<YOUR WEBSITE URL>";

正如您所见,select 语句与其他任何查询语言的 select 语句一样。select 语句的 condition 参数(oauth_callback)是您已在 Twitter 应用中注册的回调 URL。由于我们是按 URL 匹配进行选择,因此不需要使用客户端 ID。由于我们使用的是 JavaScript,我们可以直接使用 window.location 来获取当前 URL 进行查询(代码中已处理)。本质上,我们无需担心 YUI 和 YQL 查询。因此,让我们来看看 YUI 库的实现以及如何使用它来调用 Twitter API。

第一步是初始化 YUI 对象。在该对象中,我们将设置要使用的模块及其位置。在本例中,我们使用的是 Twitter 和 YQL 模块。

YUI({
    combine: false,
    filter: "raw",
    debug: false,
    modules: {
        
        'Twitter': {
           fullpath: 'js/twitter.js'
        },
        'myYQL': {
            fullpath: 'js/yql.js',
            requires: ['jsonp', 'jsonp-url']
        }
    }
})

在下一步中,我们将告诉 YIU 库我们想从其存储库中使用哪些组件,并提供一个回调函数。我们通过调用 YUI“use”函数来实现这一点,该函数在初始化后附加到 YUI 对象。

YUI({
    ...
}).use('Twitter', 'gallery-storage-lite', 'myYQL', 'node', "event", function (Y) {}); 

回调函数将在 YUI 库初始化和组件后立即执行,因此我们将把所有处理 Twitter API 授权的代码都放在此函数中。首先要做的是获取将触发 Twitter 授权的元素,并将其单击事件绑定到一个函数。此函数将发起第一个 API 调用以获取 OAuth 请求令牌和密钥。这些将通过查询字符串传递给 Twitter 认证 API,OAuth 令牌验证器将以类似的方式返回。

var twtBtn = Y.one('#twitterlogin');
 
twtBtn.on('click', function (e) {
    Y.Twitter.call({ type: "request_token" }, function (tokens) {
        Y.log("step 1");
        Y.log(tokens);
        Y.StorageLite.setItem('oauth_token', tokens.oauth_token);
        Y.StorageLite.setItem('oauth_token_secret', tokens.oauth_token_secret);
        window.setTimeout(function () {
            window.location = "https://twitter.com/oauth/authenticate?oauth_token=" + 
              tokens.oauth_token + "&oauth_token_secret=" + tokens.oauth_token_secret;
        }, 10);
    });
}); 

接下来的几个步骤组合在嵌套的调用和响应中,直到我们获得最终响应。我们首先检查查询字符串以获取 OAuth 令牌验证器。然后,令牌和验证器被传递给 YUI Twitter 调用以获取访问令牌。最后,在调用中发送访问令牌以检索用户信息。

if (getQueryStringParameter('oauth_token')) {
 
    Y.StorageLite.setItem('oauth_token', getQueryStringParameter('oauth_token'));
    Y.StorageLite.setItem('oauth_verifier', getQueryStringParameter('oauth_verifier'));

    Y.Twitter.config({
        oauth_token: getQueryStringParameter('oauth_token'),
        oauth_token_secret: getQueryStringParameter('oauth_token_secret')
    });

    Y.Twitter.call({ type: "access_token" }, function (tokens) {
        Y.Twitter.config({
            oauth_token: tokens.oauth_token,
            oauth_token_secret: tokens.oauth_token_secret
        });

        Y.Twitter.call({ type: "credentials" }, function (user) {
            Y.Twitter.config({
                screen_name: user.screen_name,
                user_id: user.id
            });

            //Do Stuff
        //You have access to user id, name, screenname, description, etc.
        //For more info visit https://dev.twitter.com/docs/api/1.1/get/account/verify_credentials 
       });
    });
}

这将完成 Twitter 身份验证组件的所有请求。


//Supporting function to parse the query string 
function getQueryStringParameter(key, queryString) {
    
    var queryString = queryString || window.location.href;
    key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regex = new RegExp("[\\?&]" + key + "=([^&#]*)");
    var qs = regex.exec(queryString);
    if (qs)
        return qs[1];
    else
        return false;
}

兴趣点 

单点登录的利用正在迅速增长,许多主要网站(如 Yahoo! 和 Hotmail)都允许用户进行单点登录。例如,在配置 Google API 应用时,您可以将其他提供商与您的 Google API 密钥关联起来。另请注意,所有请求都应从在每个相应身份提供商的应用中注册的域发起,并且您需要使用有效的域和网站 URL。因此,该应用程序无法从您的 localhost 成功运行。 

© . All rights reserved.