启用edX的所有API,可能是折腾edX以来遇到的最为艰难的问题之一(另一个是data analytics),前后利用晚上和周末的时间,折腾了好几周。

困难主要因为文档不全或是没有,甚至有些措辞含糊,几次把我带入歧途,而社区里几乎找不到任何这方面的资料,有人提过此类问题,无一得到解决方案,无论是google group还是github。

而这一块大家又都很关心(无论是社区还是国内edX开发者),因为edX的开放平台本质上就是开放的API,而edX的安卓和iOS与后端平台的通信,本质也都是基于oauth的API调用。

上个月末收到一份邮件说,他们近期的工作主要集中在支付宝接口和微信端,问我是否有兴趣同他们协作(我此前有处理过这方面的经验),他们应该是国内edx方面最具实力的团队之一了吧,我自然是很乐意的。业余时间(晚上和周末)同他们协作。

暂时为内部项目,也尚有些样式的工作未完成,不方便公开,在此给大家提供大致的方向。

#just do it

##思路 我们首先做任务陈述:允许edx用户通过微信公众平台访问edX,登录以及请求相关的数据

这里假设读者们已经基本了解了OAuth2,包括它的一些基本概念和通信流程,如果还不了解,请先阅读OAuth2相关的材料。

在我们的任务中,我们先识别出OAuth中的参与实体,RO(resource owner),RS (resource server)和Client,至于AS(authorization server)在edx中和RS可以认为一体。

很显然我们的任务中,edx平台作为RS,而edx user是RO,而我们自己写的微信公众号后台便是Client。

由于edX微信后端和edX平台拥有者是相同的,所以我就不采用redirect的方式了。而假设Client是受信任的。

那么通信的流程是这样的:edx user通过微信公众号中给Client发送账号和密码,而后Client携带用户账号和密码去换取授权令牌(Access Token),且存下授权令牌,如此一来,概念上,用户在微信中便已经保持登录edX的状态了。

而后Client根据用户请求,携带Access Token去服务器请求资源返回给微信用户。

这里不应当混淆的是,使用微信账户登录edx,和在微信中以edx user身份访问edx,是两个完全不同的过程,使用微信账户登录edx本质上是个第三方社交账号登录edx的问题,RS是微信,而edx user在微信中访问edx,RS是edX。


ps:当然最后为了使用网页来呈现edX api返回的用户相关数据(美化),我最后把使用微信账户登录edx也做了。注意:

  • 这不是必须的
  • 这会造成有两个oauth的问题
  • 这是为了样式上的美观

如果你只用文本或是图文与用户交互,实际上不需要这步


好了,思路基本清晰了。

##先前的经验 之前写过一篇博客:让edx为手机端提供接口

本打算按照之前的经验,却发现,采用TokenAuthentication的解决方案除了侵入性太强,不够优雅之外,安全性也得不到保证

EdX API Authentication中有一句话,

OAuth 2.0 is an open standard used by many systems that require secure user authentication

我开始以为,secure只是个建议,稍后我们会发现,这是个强制要求。

我顺着API接口,从url一路跟踪到view里,看到,所有的api都是基于OAuth2Authentication, SessionAuthentication认证的。虽说使用我前一篇博客提到的TokenAuthentication认证方法,理论上也是可行的,可是却要为每个接口代码注入TokenAuthentication认证方式,很不友好,另一方面,安全性上也不如OAuth2。

顺带提一下,无论是OAuth2Authentication, SessionAuthentication还是TokenAuthentication,本质都是个认证问题,而认证过程在django中间件里实现,对关注业务逻辑的开发者而言是透明的,而edx的api使用的统一是OAuth2Authentication和SessionAuthentication。

那么思路基本就清晰了,可选的路线只有一条,绕不过OAuth2.

在文档跟不上源码,社区反馈寥寥的情况下,阅读源码,根据语义和通常的习惯做法,猜测,实验,验证,基本就是我的摸索方案了

##接下来你要做的 * 走通OAuth2的流程(安全链接是个强制前提!) * 推荐使用httpie替代curl做实验。而在微信后端的Python脚本中,用来请求API的工具推荐用requests * 福利:如果你走通了edX OAuth2的流程,实际上手机端编译使用的问题也解决了! * 开启所有API接口,并阅读文档EdX Platform APIs