一,准备好开发者账号
开发者账号怎么设置我就不说了。和人人平台基本一样。很多平台都这样。
在得到 Application ID (App ID/ API Key) 和 Application secret(App Secret) 之后,记录好这两项,准备做接入。当然,还要牢记你自己的Canvas Page。
好,下一步。在开发者账号创建了这个应用之后,你可以访问一下Canves Page。
例如:http://apps.facebook.com/xxxapptest/
看一下效果。正常的话,可以看到连接到你的网站主页上了。
二,认证与授权
Facebook平台的身份验证和授权是基于OAuth 2.0协议的( OAuth 2.0 protocol )。
用户在登录之后可以有两种方式做身份验证和授权:服务器端(server-side)和客户端(client-side)。无论用哪种,都需要遵守下面的三步:用户身份验证(user authentication),用户授权 (app authorization) ,和 应用身份验证(app authentication)。 用户身份验证是确认用户身份;用户授权是让用户确认将会提供给应用什么样的个人数据和内容;应用身份验证是确认用户把他们的资料给的是你的应用,而不是别人。一旦这些步骤完成了,你的应用将会获得到一个用户访问令牌( user access token ),这样你的应用就能获取到用户的信息,并且可以获取到用户的活动和行为了。
----------------------------------------------------------------------------------------------
1. 用户授权 (user authorization)
下边我只说服务器端的认证授权流程。
获取用户基本信息的授权方式:
用户第一次登陆,facebook把用户跳转到我们的应用服务器,那么我们要调用这样一个url:
https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL
其实就是调用facebook的标准认证对话框(OAuth Dialog)。如果用户点击确认了,注意,这个授权,应用只能是获取到用户的基本信息的,也就是facebook上用户的公共信息。例如ID,主页,用户的名字。
获取用户的其他信息的授权方式:
如果想获取到用户的其他信息,就必须明确的告诉用户,你的应用需要哪些用户的信息,像下面这样:
https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&scope=email,read_stream
scope参数里面,指定了你的应用想要获取的用户信息。
用户同意授权
假如用户点击了同意(Allow),那么你的应用就会被用户授权了。授权对话框( OAuth Dialog)将会带着认证码(authorization code)参数跳转(via HTTP 302)到你的服务器的url。我查看了整个授权后的request,发现,facebook把认证码放在了GET里,其他的信息在POST里。GET里面会有一个code参数,好长一串,这个就是授权码。有了这个code,我们就可以进行下一步应用身份验证了。
----------------------------------------------------------------------------------------------
2. 应用身份验证(app authentication)
为了验证你的应用(app),你必须把上面得到的授权码(authorization code)和你的应用密钥(App Secret)传给 Graph API的令牌终点( token endpoint):
https://graph.facebook.com/oauth/access_token
格式是这样的:
https://graph.facebook.com/oauth/access_token?
client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&
client_secret=YOUR_APP_SECRET&code=THE_CODE_FROM_ABOVE
如果你的应用成功的通过了认证,并且你的用户的授权码也是合法的,那么授权服务器将会返回访问令牌(access token)。
----------------------------------------------------------------------------------------------
现在我们来看一下,网站接收到的facebook传来的request的POST数据:
注意,此时是在没有授权的情况下,从平台发过来的请求。
u'fb_sig_time': [u'1310471486.9658'],
u'fb_sig_added': [u'0'],
u'fb_sig_locale': [u'zh_CN'],
u'fb_sig_in_iframe': [u'1'],
u'fb_sig_in_new_facebook': [u'1'],
u'fb_sig_country': [u'us'],
u'fb_sig': [u'6edf97802d706b84753a4a328d65b1cc'],
u'fb_sig_api_key': [u'6361833388ca80696ad667af7abcceee'],
u'fb_sig_app_id': [u'120306072668168']
好,按照facebook的规则,要想得到用户的信息,你的这个应用必须得到用户的授权(Authorization)。这个授权,就好比,用户在facebook上,确认安装你的游戏。
授权的格式,开发者文档写的很明白:
https://www.facebook.com/dialog/oauth?
client_id=YOUR_APP_ID&redirect_uri=YOUR_CANVAS_PAGE
上面我们说的Application ID (app ID)和Canves Page在这里就能用得上了。
在浏览器中输入这个授权url,就会看到你的应用的用户授权页。
当用户点击确定授权的时候,facebook将会给我们的网站发来这样的request内容:
POST:
u'fb_sig_time': [u'1310627493.7758'],
u'fb_sig_added': [u'1'],
u'fb_sig_locale': [u'zh_CN'],
u'fb_sig_in_iframe': [u'1'],
u'fb_sig_in_new_facebook': [u'1'],
u'fb_sig_profile_update_time': [u'1256108103'],
u'fb_sig_country': [u'us'],
u'fb_sig_ss': [u's2Ke_YrygH7T8aEd9Lmcrg__'],
u'fb_sig_user': [u'100000413372683'],
u'fb_sig_cookie_sig': [u'3bce4346fd8f2f62c347eae9e89ae2d8'],
u'fb_sig_session_key': [u'2.AQC9WncK12nGzWCn.3600.1310634000.0-100000413372683'],
u'fb_sig_expires': [u'1310634000'],
u'fb_sig': [u'af28d8df0e0ec5fbbf01ec430622278d'],
u'fb_sig_api_key': [u'6361833388ca80696ad667af7abcceee'],
u'fb_sig_app_id': [u'120306072668168']
可以看见,POST里面已经有了uid了。
授权(authorization)
为了给用户创造人性化(personalize)的体验,Facebook将把用户的信息,在用户允许的情况下发送给你的应用。这些信息将通过HTTP POST里的 signed_request 参数传给你的应用。 signed_request 其实就是一个经过base64url 编码的JSON对象。所以,在你解码之前,signed_request的内容看上去就是一个用点(.)分割的长串数据。
用户第一次访问你的应用的时候,signed_request参数只包含下面这些数据(如果你看不到数据,只看到一长串字母数字,那请先看下边的解码签名请求)。可以看到,几乎没有什么有用的用户数据:
Name | Description |
---|---|
user |
A JSON array containing the locale string, country string and the age object (containing the min and max numbers of the age range) for the current user. 里面只有local,county,和age 没有uid 和token! |
algorithm |
A JSON string containing the mechanism used to sign the request. |
issued_at |
A JSON number containing the Unix timestamp when the request was signed. |
为了获取有用的用户信息,比如用户在Facebook的ID,那么你需要得到用户的授权。官方建议是使用认证对话框(OAuth Dialog) 进行用户对应用的授权。怎么引用这个对话框,进行授权呢?其实就是在你的服务器端或者页面端,跳转到 Facebook指定的URL。这个URL规则如下:
https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=YOUR_CANVAS_PAGE
当跳转到这个URL的时候,就会出现facebook标准的认证对话框了。注意,上面这种规则的URL授权对话框,你的应用只能是获取到用户的基本信息的,也就是facebook上用户的公共信息。例如ID,主页,用户的名字。如果你想获取到用户的其他信息,就必须明确的告诉用户,你的应用需要获取哪些用户的信息,像下面这样:
https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&scope=email,read_stream
注意,scope参数里面,指定了你的应用想要获取的用户信息。
假如用户点击了同意(allow),那么用户就对应用授权了。授权后,signed_request参数将含下面这些数据。可以看到,可以得到重要的两项:用户的id,就是user_id;和oauth_token 。
Name | Description |
---|---|
user |
A JSON array containing the locale string, country string and the age object (containing the min and max numbers of the age range) for the current user. |
algorithm |
A JSON string containing the mechanism used to sign the request. |
issued_at |
A JSON number containing the Unix timestamp when the request was signed. |
user_id |
A JSON string containing the Facebook user identifier (UID) of the current user. |
oauth_token |
A JSON string that you can pass to the Graph API or the Legacy REST API. |
expires |
A JSON number containing the Unix timestamp when the oauth_token expires. |
解码签名请求(Decode Signed Request)
Facebook把请求做了签名。形成了signed_request这个东西。signed_request 其实就是一个经过base64url 编码的JSON对象。直接取过来,就是一个用"."分割的字符串。我们要做的,是把点前面的字符串解码,就是验证是否是facebook的合法sig;把点后面的字符串解码,就是facebook传给你应用的具体数据data。
具体算法python版:
# reques就是facebook发过来的请求 params = request.POST.copy() signed_request = params.get('signed_request') # signed_request传到python这边, 数据结构是一个字符串型的list if isinstance(signed_request, list): signed_request = signed_request[0] encoded_sig, payload = signed_request.split(".", 2) # 余数2, 那么需要补一个= payload = str(payload) if len(payload)%3 == 2: payload += '=' # 余数1, 那么需要补两个= if len(payload)%3 == 1: payload += '==' # urlsafe_b64decode() Decode string s using a URL-safe alphabet, # which substitutes - instead of + and _ instead of / in the standard Base64 alphabet. # 得到data data = simplejson.loads(base64.urlsafe_b64decode(payload)) # 得到sig encoded_sig = str(encoded_sig) if len(encoded_sig)%3 == 2: encoded_sig += '=' if len(encoded_sig)%3 == 1: encoded_sig += '==' sig = base64.urlsafe_b64decode(encoded_sig)
获取用户信息
经过上面的解码签名请求后,可以获取到FB的数据了。就是上面代码里的data。如果里面有'user_id' 那么就说明,uid和oauth_toke
都有了。请注意,如果您用的是国内服务器,是不可以直接调用facebook API接口的。
if 'user_id' in data: uid = data['user_id'] params_dic = {} params_dic['uid'] = uid params_dic['oauth_token'] = data['oauth_token']
有了这uid和oauth_toke
,我们就可以获取其他的用户信息了。下面是获取几个重要接入属性的方法。如果不明白为什么这么写,可以参考facebook开发文档。
用户昵称:
graph_url = "https://graph.facebook.com/%s" % uid
facebook_usr_info = simplejson.loads( urllib2.urlopen(graph_url).read() )
name = facebook_usr_info['name']
好友列表:
graph_url = "https://graph.facebook.com/me/friends?access_token=%s" % oauth_token
f_dic = simplejson.loads(urllib2.urlopen(graph_url).read())
friends_ids = f_dic['data']
头像:
headurl = 'http://graph.facebook.com/' + uid + '/picture'