引言
近期在做开源项目登录的时候除了使用账密
登录以外,还想引入基于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操作做了封装,所以操作起来比较简单