前面我們自己寫了一個簡單的登陸認(rèn)證系統(tǒng),即用戶在登陸時,通過輸入事先注冊的用戶名和密碼,服務(wù)器確認(rèn)用戶的身份后,從而獲得操作權(quán)限。這也是最傳統(tǒng)的登陸認(rèn)證方式。
隨著互聯(lián)網(wǎng)的不斷開放與發(fā)展,又出現(xiàn)了一種新的登陸認(rèn)證方式——第三方登陸認(rèn)證,即我們常說的oAuth/oAuth2.0。
OAUTH協(xié)議為用戶資源的授權(quán)提供了一個安全的、開放而又簡易的標(biāo)準(zhǔn)。與以往的授權(quán)方式不同之處是OAUTH的授權(quán)不會使第三方觸及到用戶的帳號信息(如用戶名與密碼),即第三方無需使用用戶的用戶名與密碼就可以申請獲得該用戶資源的授權(quán),因此OAUTH是安全的。
Passport是一個基于Node.js的認(rèn)證中間件。極其靈活并且模塊化,Passport可以很容易地跟任意基于Express的Web應(yīng)用結(jié)合使用。 現(xiàn)在我們來修改代碼,使得我們的博客既支持本地登陸又支持使用 GitHub 賬戶登錄。
首先,登錄 GitHub ,點擊右上角的 Account settings ,然后點擊左側(cè)的 Applications ,然后點擊右上角的 Register new application 創(chuàng)建一個 GitHub 應(yīng)用。
創(chuàng)建成功后如下圖所示:
http://wiki.jikexueyuan.com/project/express-mongodb-setup-blog/images/7.1.jpeg" alt="" />
稍后我們將會用到 Client ID 、Client Secret 和 Authorization callback URL。
打開 package.json ,添加 passport 和 passport-github 模塊:
"passport": "*",
"passport-github": "*"
并 npm install 安裝這兩個模塊。
至此,準(zhǔn)備工作都已完成,接下來我們修改代碼支持使用 GitHub 賬戶登錄。
首先,添加使用 GitHub 登陸的鏈接。打開 login.ejs,在:
<%- include footer %>
上一行添加如下代碼:
<a href="/login/github">使用 GitHub 登錄</a>
然后打開 app.js ,在 var app = express(); 下添加如下代碼:
var passport = require('passport')
, GithubStrategy = require('passport-github').Strategy;
在 app.use(app.router); 上添加一行代碼:
app.use(passport.initialize());//初始化 Passport
在 if ('development' == app.get('env')) 上添加如下代碼:
passport.use(new GithubStrategy({
clientID: "xxx",
clientSecret: "xxx",
callbackURL: "xxx"
}, function(accessToken, refreshToken, profile, done) {
done(null, profile);
}));
注意:將 clientID、clientSecret 和 callbackURL 分別替換為剛才創(chuàng)建 GitHub 應(yīng)用得到的信息。
以上代碼的意思是:我們定義了一個 Passport 策略,并嘗試從 GitHub 獲得授權(quán),從 GitHub 登陸并授權(quán)成功后以跳轉(zhuǎn)到 callbackURL 并以 JSON 形式返回用戶的一些相關(guān)信息,并將這些信息存儲在 req.user 中。
打開 index.js ,在上方添加一行代碼:
var passport = require('passport');
并在 app.get('/login') 后添加如下代碼:
app.get("/login/github", passport.authenticate("github", {session: false}));
app.get("/login/github/callback", passport.authenticate("github", {
session: false,
failureRedirect: '/login',
successFlash: '登陸成功!'
}), function (req, res) {
req.session.user = {name: req.user.username, head: "https://gravatar.com/avatar/" + req.user._json.gravatar_id + "?s=48"};
res.redirect('/');
});
這里我們可以直接使用 Express 的 session 功能,所以禁掉 Passport 的 session 功能,前面提到過 Passport 默認(rèn)會將取得的用戶信息存儲在 req.user 中而不是 req.session.user,為了保持兼容,所以我們提取并序列化有用的數(shù)據(jù)保存到 req.session.user 中。
至此,我們的博客也支持 GitHub 登錄了,是不是很簡單?目前還存在三個問題:
第一個問題的簡單粗暴的解決方法是當(dāng)用戶以 GitHub 賬戶登錄時,把獲取的用戶名到本地數(shù)據(jù)庫查一下,若存在則禁止登錄,若不存在則允許登陸。
第二個問題修改一下代碼即可解決,刪除 index.js 中 app.get('/u/:name') 內(nèi)的那層判斷數(shù)據(jù)庫中是否存在該用戶名的函數(shù)即可。
第三個問題暫時無法解決,因為 GitHub 返回的信息中并不包含有效的用戶郵箱。