使用新浪微博API:创建站内应用

廖雪峰 / 文章 / ... / Reads: 1617 Edit

站内应用是直接嵌入到新浪微博的一种应用,用户在使用站内应用时,仍访问新浪微博的网站,而具体的站内应用则以iframe的形势嵌入页面。由于这种应用不同于第三方网站,不能通过新浪微博的授权页跳转实现授权,所以,获得用户授权稍有不同。

创建站内应用时,首先,需要申请站内应用,除了App ID,App Secret外,还有新浪微博分配的站内应用的地址和应用的实际地址,即iframe加载的网站地址。以下代码是站内应用apps.weibo.com/irunning的常量定义。代码如下:

_APP_ID = '12345'
_APP_SECRET = 'abc123xyz'
_APP_URL = 'http://apps.weibo.com/irunning'
_SERVER_URL = 'http://weiborun.sinaapp.com/'

当用户在新浪微博网站内访问http://apps.weibo.com/irunning时,新浪微博会发送POST请求至内嵌的iframe,因此,我们的后台服务http://weiborun.sinaapp.com/会收到该POST请求,并获取signed_request参数,我们需要从signed_request中获取加密的参数。代码如下:

@post('/')
def index():
    data = _parse_signed_request(ctx.request['signed_request']))
    if data is None:
        # 用户未授权,返回授权页:
        raise seeother('/auth.html')
    # 用户已授权,获取OAuth token:
    access_token = data['oauth_token']
    expires = data['expires']
    client = _create_client()
    client.set_access_token(access_token, expires)

def _parse_signed_request(sr):
    def _b64_normalize(s):
        ' 还原Base64编码字符串 '
        appendix = '=' * (4 - len(s) % 4)
        return s.replace('-', '+').replace('_', '/') + appendix

    sr = str(signed_request)
    logging.info('parse signed request: %s' % sr)
    enc_sig, enc_payload = sr.split('.', 1)
    # 获得Digest:
    sig = base64.b64decode(_b64_normalize(enc_sig))
    # 获得JSON数据:
    data = _parse_json(base64.b64decode(_b64_normalize(enc_payload)))
    if data['algorithm'] != u'HMAC-SHA256':
        return None
    # 计算Digest:
    expected_sig = hmac.new(self.client_secret, enc_payload, hashlib.sha256).digest();
    # 与新浪微博发送的Digest对比是否一致:
    if expected_sig==sig:
        if data.get('oauth_token', None) is None:
            return None
        return data
    return None

新浪微博传入的signed_request字符串参数通过解码后拿到HMAC-SHA256签名和原始JSON数据,此时,我们需要根据App Secret自己计算出签名,并与新浪微博传入的签名对比,若一致,则说明JSON数据有效,否则,说明数据是第三方伪造的。由于App Secret只有我们的站内应用和新浪微博持有,因此,第三方是无法伪造签名的。

验证了签名后,即可从JSON数据中获取oauth_token参数。若oauth_token参数为空,则表示用户未授权,我们就给用户显示授权页auth.html,授权页源码如下,主要通过一个JavaScript调用弹出授权框给用户。

<html>
<head>
    <title>未授权时的页面</title>
    <script src="http://tjs.sjs.sinajs.cn/t35/apps/opent/js/frames/client.js" type="text/javascript"></script>
</head>
<script>
function authLoad() {
    App.AuthDialog.show({
        client_id: '12345',
        redirect_uri: 'http://apps.weibo.com/irunning',
        height: 40
    });
}
</script>
<body onload="authLoad();">
</body>
</html>

弹窗的JavaScript代码是由新浪微博提供的,效果如下:

weibo-insite-app

用户可以在弹出的授权框中授权,然后,新浪微博会再次发送POST请求至站内应用的网站,此时,从signed_request参数中即可获取到oauth_token。有了oauth_token,我们就可以用SDK调用任意的API了,包括获取当前授权用户的用户信息,以判断该用户是否是第一次访问。此后的API调用与普通Web网站是一样的,这里就不再多述。

本文的站内应用地址:

http://apps.weibo.com/irunning

本文的网站源码可以从GitHub下载:

https://github.com/michaelliao/irunning

Comments

Make a comment

Author: 廖雪峰

Publish at: ...

关注公众号不定期领红包:

加入知识星球社群:

关注微博获取实时动态: