前言
在上上篇文章里,我介绍了我的新博客系统 Solomon,其中就讲的到了我用了 GitHub Issue 做为评论系统。这么做有两个麻烦的地方:
需要为每一篇文章创建一个 issue;
评论者需要有 GitHub 帐号,然后在登录的状态下到 issue 的页面进行评论。
作为一个处女座,我觉得需要到别的页面才能评论或点赞的用户体验太糟糕了。所以,我考虑让评论者通过 OAuth 授权的方式获得 Token,然后就可以直接在文章页面进行评论了。
OAuth
OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。
via 维基百科
OAuth 的具体实现就是通过提供给第三方一个 Token,第三方就可以通过这个 Token 在特定的时间内访问特定的内容。
既然要在 GitHub 上评论,我们就需要先在 GitHub 上注册我们的应用:
打开 Developer applications 或者进入 GitHub 的设置页面,在侧边栏里选择 OAuth applicatioins。
然后选择 Register a new application 注册一个新的应用:
注意这里有个 Authorization callback URL,它是我们和 GitHub 完成授权之后的一个重定向地址,我们下面也会介绍到。
填写好信息之后点击 Register application。之后就可以看到这个界面,就代表我们的应用已经注册好了。
在这个页面我们还可以可以我们的 Client ID 和 Client Secret。
Client ID 是用于用户和 GitHub 获得授权的时候使用的,GitHub 通过这个得知你要授权的网站,并且会把该网站需要的权限列出来,让用户决定是否授权。
用户确认了之后就会跳转到我们上面提到的 Callback URL,并且返回一个 code。
我们在得到了 code 之后,将它和 Client Secret 传给 GitHub,GitHub 就会返回一个有时限的 access_token,通过这个 token 我们就能访问到 GitHub 的资源了。
但是,OAuth 授权的话意味着需要有服务器帮我们完全上述内容。这对于我这种静态博客来说是一大困难。本身就是为了节省打理服务器的时间而选择了静态博客,现在为了一个评论的功能再引入一个服务器,不免有点本末倒置。
所幸,托管我的网站的 Firebase 提供了 Firebasee Authentication,让我们可以通过 Firebasee 的服务器完成整个授权过程。
Firebase Authentication
关于 Firebase 的介绍在上上一篇我简要的介绍过了。Firebase Authentication 则是 Firebase 提供的一个身份验证服务。
Firebase Authentication 不仅可以使用传统的邮箱密码验证,还引入了一些比较流行的身份提供商,例如:Google,Facebook 和 Twitter 等:
此外,Firebase Authentication 利用了行业标准:我们上面提到的 OAuth 2.0 和 OpenID 等,所以也可以集成到自定义的后端里。
要使用 Firebase Authentication 需要先进行一下配置:首先登录到 Firebase Console。
然后在侧边栏里选择 Authentication,然后选择 Sign-in Method 子选项卡:
接下来开启 GitHub 认证,填写我们的 Client ID 和 Client secret:
注意到下面地址了吗?那个就是我们的回调地址,保存好 Firebase 这边的设置之后。我们需要回到 GitHub,把回调地址改成 Firebase 提供给我们的那个:
为了安全,Firebase 限制了只有通过认证的域名才可以通过完全整个用户认证的过程。默认的认证的域名只有 localhost 和你项目的默认地址。
所以,如果你使用了自定义域名的话。还需要把你的域名加到 OAuth redirect domains里:
Angularfire2
GitHub 和 Firebase 都设置好之后,就可以正式的使用了。
Firebase Authentication 提供了两种使用方法:FirebaseUI 和 Firebase Authentication SDK。
FirebaseUI 尚处于测试阶段,所以我这里选择用 Firebase Authentication SDK。
Firebase 提供的 Demo 是在应用的 HTML 中加入 firebase.js
文件,然后在 <script>
中定义各种操作。
既然我们已经用了 Angular,就不需要用这么麻烦的方法了。我们这里用 Angular 官方提供的库:Angularfire2。
设置 Angularfire2 很容易,先安装依赖:
$ yarn add firebase angularfire2
# or
$ npm install firebase angularfire2 --save
然后在你的根模块里加上:
export const firebaseConfig = {
apiKey: "<your-key>",
authDomain: "<your-project-authdomain>",
databaseURL: "<your-database-URL>",
storageBucket: "<your-storage-bucket>",
messagingSenderId: "<your-messaging-sender-id>"
};
@NgModule({
imports: [BrowserModule, AngularFireModule.initializeApp(firebaseConfig)],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {}
注意要将其中的 firebaseConfig
改成你的项目的配置。
配置在哪里找呢?在你的 Firebase Console 的 Overview 里点击 Add Firebase to your web app:
配置完了之后就可以使用了。例如,登录的话需要调用 AngularFire.auth#login()
:
this.af.auth
.login({
provider: AuthProviders.Github,
method: AuthMethods.Popup,
scope: ["public_repo"]
})
.then((res: any) => {
console.log(res);
if ("accessToken" in res.github) {
this.tokenService.setToken(res.github.accessToken);
} else {
this.snackBarOpen("Access Token Not Found, Re-login Please.", 1000);
}
});
这里需要注意两点:
为了安全,GitHub 只会在登录的时候返回
accessToken
。所以我们需要在发起登录请求的之后调用.then()
,获取我们需要的accessToken
,存在我们的TokenService 里或者其他地方。我们获取
accessToken
的目地是用它来调用 GitHub API,实现评论的功能的。所以我们在登录的时候需要多申请一个public_repo
的权限。否则就会出现Issue not viewable by xxx
等错误。
我一开始没发现,还去 stackoverflow 提问:https://stackoverflow.com/questions/42323439/how-to-post-comment-using-github-oauth-token-in-angular-2:(
在这里感谢一下 https://stackoverflow.com/users/1074361/pedro-nascimento,帮我找到了问题所在。:)
得到了 accessToken
之后能干的事情就有很多了,例如在 Solomon 里直接:添加/修改/ 删除评论,添加/删除 Reaction;此外还可通过 accessToken
认证每一次 GitHub API 的调用,实现增加 GitHub API 的调用上限:https://developer.github.com/v3/#rate-limiting
存在的问题
如果仔细看我上面的代码就会发现我是把 accessToken
放在了 TokenService
,而没有使用持久化存储,例如数据库等。这样的话,意味着每次浏览完 Solomon,关闭页面之后,下次再来的话,就需要重新登录一遍了。
当然,也不是没有办法,Firebase 还提供了实时数据库,可以把 accessToken
存在里面。
不过这样就意味着我可以直接接触到 accessToken
。虽然这个 accessToken
的权限不多,只能访问公共仓库,而且有时限。但是我还是不希望让整个认证的过程变得不那么透明,所以目前还是保留这个问题。
后语
就像我上一章里介绍了 Firebase Hosting 之后说的那样。Hosting 和 Authentication 只是 Firebase 众多功能中的两个而已:
Firebase 还有更多非常使用的功能,像上图中的 Analytics(用户分析),Datebase(实时数据库),Crash Reporting(错误追踪),Test Lab(测试平台,测试 Android 应用的兼容性),Notifications(云推送)和AdMob(广告获利)等才是 Firebase 的大杀器。
所以,Google 大法好。:)