引言
近期在做開源項目登錄的時候除了使用賬密
登錄以外,還想引入基於OAuth 協議的 Github
第三方登錄,於是便有了下文的記錄。
不瞭解OAuth協議的看阮老師的這篇文章 理解OAuth 2.0
Egg中使用 Passport 鑑權
見 官方文檔
由於Egg 在Passport之上提供了 egg-passport 插件,把初始化、鑑權成功後的回調處理等通用邏輯封裝掉,使得我們僅需調用幾個 API 即可方便的使用 Passport 。
下面主要對獲取到github用戶登錄信息後如何處理做簡要說明
掛載路由
// router.js
// 掛載github鑑權路由
const github = app.passport.authenticate('github', {
successRedirect: app.config.passportGithubSuccessRedirect, // 配置鑑權成功後的跳轉地址
});
apiV2Router.get('/passport/github', github);
apiV2Router.get('/passport/github/callback', github);
// config.default.js
// 配置 passportGithub
config.passportGithub = {
key: 'your_clientID',
secret: 'your_clientSecret',
// 獲取github用戶信息,該路由上攜帶授權碼,我的路由都在 /api/v2 命名空間下,默認爲 /passport/${strategy}/callback
callbackURL: '/api/v2/passport/github/callback',
// proxy: false,
};
// 配置github登錄成功後的跳轉地址
config.passportGithubSuccessRedirect = 'http://127.0.0.1:3000/#/';
用戶信息處理
用戶表字段
provider
: 表示第三方登錄的名稱,比如(github, facebook)
uid
: 表示第三方登錄用戶的唯一標識
thirdPassUpdate
: 標識第三方登錄用戶是修改了密碼
app.js做初始化
'use strict';
const jwt = require('jsonwebtoken');
module.exports = app => {
// 校驗github用戶登錄信息(包括首次以及多次登錄的處理)
app.passport.verify(async (ctx, user) => {
// user即爲github提供的用戶信息
const existsUser = await ctx.model.User.findOne({
where: { uid: user.id },
});
if (existsUser) {
const token = jwt.sign({ userId: existsUser.userId }, app.config.jwt_secret, { expiresIn: '7d' });
await ctx.service.user.setCookie(token); // 設置登錄用戶cookie信息,以避開系統接口訪問攔截
return existsUser;
}
// 首次github登錄,調用 service 註冊新用戶
const newUser = await ctx.service.user.commonRegister({
username: user.name,
password: app.config.passportGithubPassword, // github登錄用戶統一初始化密碼,在進入系統後強制修改密碼
email: user.profile._json.email,
provider: user.provider,
uid: user.id,
thirdPassUpdateStatus: 0, // 0 代表爲初次登錄未修改過密碼
avatarUrl: user.photo,
abstract: user.profile._json.bio,
});
const token = jwt.sign({ userId: newUser.userId }, app.config.jwt_secret, { expiresIn: '7d' });
await ctx.service.user.setCookie(token);
return newUser;
});
};
最後因爲 egg-passport 及 egg-passport-github 對passport操作做了封裝,所以操作起來比較簡單