网站接入微博开放平台

全篇共 5096 字。按500字/分钟阅读速度,阅读完预计需要 10.2 分钟。

提交网站接入申请

微博开放平台网站接入 页面开始创建自己的应用,按提示一步一步填写表单项。唯一有一点麻烦的是还要准备:

  • 3种尺寸的应用图标
  • 3张用于描述应用的图片

我的个人网站的图标是用Photoshop设计的,图标中的红绿蓝三原色表示我的网站内容是由技术、艺术与国学三种元素组成,但是后来我为了让个人品牌更清晰,就把图标改成了“帅华”两个字。用Photoshop导出不同尺寸图片的技巧是:

  1. 使用Ctrl+Alt+Shift+C快捷键导出图片
  2. 在导出设置面板中修改图片导出尺寸和格式
  3. 如果对导出图片的大小也有限制,就适当降低导出图片的品质

帅华君博客申请微博网页应用各个尺寸图标

我直接使用截图工具,截了三张能代表网站内容的图片,再用Photoshop逐一调整图片的尺寸、格式和品质,以符合要求。

帅华君博客申请微博应用准备图片介绍

所有表单项都填写明白后,提交表单,等待接受微博开放平台工作人员的审核。别忘了在你的网站主页放置一个微博组件,这也是需要审核的一项,我在网站主页放置了一个微博关注按钮组件。申请审核通过后,你就就可以把这个组件去掉,也可以继续保留。

收到微博开放平台应用审核通过的邮件提醒

审核挺迅速的,在一个工作日内,我陆续收到应用审核通过的邮件通知。每一次你更新应用设置后,都会重新进入上面的审核阶段,比如上面第二封邮件就是第二次审核通过后的邮件通知,因为我修改了微博授权回调地址。创建网站接入用途的应用申请通过后,你就能看到你申请的应用的状态变成了“上线”。

帅华君的原创博客已经通过微博开放平台的应用申请

我本来打算继续“申请广场”的,但是申请被驳回,原因是微博的应用广场已下线。

引导用户完成授权

用户授权网站接入其微博账号的流程大致如下:

  1. 你成功申请下来网站接入微博的权限后,你会在应用基本信息中看到两个非常重要的参数:App KeyApp Secret,前者就是公钥,可以公开,比如我的App Key是1434077908,后者就是私钥,绝对不能公开。

    App Key: 1434077908
    App Secret: *********************
    
  2. 在你的网站放置一个登录按钮,用户点击该按钮后跳转到微博的授权界面。跳转链接的格式如下,它包含了 client_idresponse_typeredirect_uri这三个GET请求的查询参数,其中第一个参数就是你的App Key的值,第二个参数永远是code,第三个参数是当微博授权结束后跳转的回调页面,也就是你网站上某个专门处理微博授权结果的回调地址。下面是我让用户授权我的网站接入他的微博的完整跳转地址,你可以按照这个格式替换成你的client_idredirect_uri

    https://api.weibo.com/oauth2/authorize?client_id=1434077908&response_type=code&redirect_uri=http://www.shuaihuajun.com/weibo_oauth/
    
  3. 用户跳转到微博的授权界面,有两个选择按钮,一个是确认授权,另一个是不授权。无论用户是否确认授权,都会在点击按钮后跳转到你网站处理授权结果的地址。如果用户确认授权了,会在你网站的回调地址后添加code查询参数。如果用户不授权,也会跳转到你网站的回调地址,不过没有code查询参数。下面是用户确认授权后完整的跳转地址,会携带code参数。

    http://www.shuaihuajun.com/weibo_oauth/?code=6c3bd9ad464362ca780c36219497ecb4
    
  4. 你首先要判断是否携带了code参数,如果没携带,而且携带的是包含错误信息的查询参数,表示用户不允许授权,你可以将授权失败的结果返回到前端页面上,以告知用户。但我想重点谈一谈的是,当用户确认授权后,携带着code查询参数访问了你网站的回调地址,你该做些什么。

用code换取access_token

文章写到这里,就要开始写代码了。首先声明我网站的后端是用Node+Express框架开发。从上面你已经知道了,我的处理授权结果的回调地址是:http://www.shuaihuajun.com/weibo_oauth/,使用中间件处理所有对该地址的请求。示例代码如下,但并不代表真实情况。而且你已经能从请求对象中拿到code值了:

app.get('/weibo_oauth/', (req, res) => {
  const CODE = req.query.code;
    // 因为无论用户是确认授权还是拒绝授权,都会跳转到该路由中。
    // 通过判断请求中是否携带code值,就能判断用户是否确认授权。
    // 尽管会有携带虚假code值的恶意请求,但不实的code值并不能成功换取access_token。
    if (!CODE) {
    res.status(404).end('code?');
    return;
  }
});

拿到code值后就要向微博开放平台发起换取access_token的POST请求了。我已经提前封装好了在Node中向某网址发起POST请求的工具函数,叫postRequest,它返回一个Promise实例,你可以使用Async/Await语法使用它:

// hostname: 主机地址,如 api.weibo.com
// path: 路径,如 /oauth2/access_token
// content: 准备POST的数据
const postRequest = (hostname, path, content) => {
  return new Promise((resolve, reject) => {
    // 准备请求选项,设置主机名、路径、请求方法、请求头信息
    const options = {
      hostname: hostname,
      path: path,
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': Buffer.byteLength(content)
      }
    };
    // 发起https协议的请求
    const req = https.request(options, res => {
      res.setEncoding('utf8');
      let data = '';
      res.on('data', chunk => data += chunk);
      // 响应信息接收完毕后执行 resolve 回调函数
      res.on('end', () => resolve(JSON.parse(data)));
    });
    // 处理错误
    req.on('error', err => reject(err));
    req.write(content);
    req.end();
  });
};

回到我们换取access_token的业务逻辑上。使用上面postRequest工具函数向能够用code值换取access_token的微博开放平台的接口地址发起POST请求。完整的接口地址是:https://api.weibo.com//oauth2/access_token。

let accessToken = {};
try {
  accessToken = await utils.postRequest('api.weibo.com', '/oauth2/access_token', querystring.stringify({
    'code': CODE,
    // 对应App Key
    'client_id': '1434077908',
    // 对应App Secret
    'client_secret': '*****************',
    'grant_type': 'authorization_code',
    // 回调地址
    'redirect_uri': 'http://www.shuaihuajun.com/weibo_oauth/'
  }));
} catch (e) { };
if (!accessToken.access_token || !accessToken.uid) {
  res.status(404).end('access_token? uid?');
  return;
}

获取微博用户信息

拿到了access_token后,就能向其他需要access_token参数的接口发送请求了,比如获取微博用户信息的接口用GET请求方法发送请求,需要提供access_token和uid两个参数,这两个参数我们已经获取到了,就存储在accessToken变量引用的对象里。

`https://api.weibo.com/2/users/show.json?access_token=${accessToken.access_token}&uid=${accessToken.uid}`;

获取微博用户信息的接口,使用GET方法请求。我已经封装好了用于GET请求的工具函数,构造GET请求比POST请求简单一些。该工具函数同样返回一个Promise实例:

const getRequest = uri => {
  return new Promise((resolve, reject) => {
    https.get(uri, res => {
      let data = '';
      res.on('data', chunk => data += chunk);
      res.on('end', () => resolve(JSON.parse(data)));
    }).on('error', err => reject(err));
  });
};

继续回到业务代码中来,获取微博用户信息:

const user = await utils.getRequest(`https://api.weibo.com/2/users/show.json?access_token=${accessToken.access_token}&uid=${accessToken.uid}`);

解除授权

微博用户可以单方面解除授权,同样,网站也可以单方面解除用户的授权。用户如果想自己解除授权,就到个人设置里解除对某个应用的授权,网站就不再有权限接入你的微博了。网站如果想解除某个或一批用户对网站的授权,也是通过访问接口的形式实现,解除授权的地址如下:

https://api.weibo.com/oauth2/revokeoauth2

该接口支持GET和POST两种请求方法,这里我还使用POST方法向该地址发送请求,请求需要携带access_token参数:

const revokeResult = await util.postRequest('api.weibo.com', '/oauth2/revokeoauth2', querystring.stringify({
  'access_token': access_token,
}));

网站成功解除授权后,响应消息如下:

{
  "result": "true"
}

授权我的个站

如果你想亲身体验一下上面的流程,请访问 授权网站接入微博。如果你想解除授权,请访问 解除接入微博的授权

第一次授权成功后,你就能看到你的微博公开的资料,你不公开的那些资料只有微博官方能看到,我的网站是看不到的。解除授权后,再次授权时我的网站不会再去获取一遍你全部的公开资料,只会返回给你数据库中的个别信息,比如用户名、uid等。在没有解除授权的情况下重新授权,你会收到repeat提示,这是因为我禁止了重复授权。


扩展阅读:

原创作者 » 陈帅华
版权声明 » 自由转载-保持署名-非商用-非衍生
发布日期 » 2019年11月27日 周三
更新日期 » 2020年8月1日 周六
上一篇 » 观纪录片《苏东坡》有感
下一篇 » Airglass可视化想法频率
:)记录此刻想法
请选择登录方式,开始记录你的想法。
授权微博登录
授权Github登录