用PassportJS实现多账号登录

HomeNodejs用PassportJS实现多账号登录

是否曾想使用Google的账户来登录你的应用?或者是微博、QQ?恩。今天介绍一下使用 PassportJs 验证身份,支持 N 多种网站登录哦。

同样,本文的大部分内容都是从Danial Khosravi上学习的。经过一番折腾之后,我发现挺不错的。唯一一个问题,就是国内需要「翻墙」,这里不得不使用 GitHub 来演示代码。

同理,介绍下这篇文章的目录索引:

什么是 PassportJs ?

PassportJs是一个 NodeJS 的中间件模块。非常灵活并且模块化,使用它可以轻松地让Facebook、Twitter或者其他社交网站的用户登录到你的应用。

一、如何安装 PassportJS 到你的应用?

使用npm来安装 PassportJS

$ npm install passport

因为这里需要让 GitHub 的用户登录到你的应用,所以需要安装 PassportJS 的插件,还有一个本地插件也是需要安装下来。

$ npm install passport-local
$ npm install passport-github

二、添加 PassportJS 的中间件

和上一篇文章介绍的一样,除了普通的依赖之外,还需要添加 PassportJs 的中间件到应用中来:

app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({ secret: 'SECRET' }));
//下面两条就是passportjs的中间件引用
app.use(passport.initialize());
app.use(passport.session());

三、数据库和模块

同样,这里使用MongoDB来作为数据库。所以:

  • 需要通过mongod来启动 mongo;
  • 创建应用并链接数据库的方法:mongoose.connect("mongodb://localhost/myapp");
  • 设置本地用户表:
var LocalUserSchema = new mongoose.Schema({
    username: String,
    salt: String,
    hash: String
});

var Users = mongoose.model('userauths', localUserSchema);

我们需要在用户表里面创建一个字段,用于存放来自 GitHub 用户的信息。

var GithubUserSchema = new mongoose.Schema({
    fbId: String,
    email: { type : String , lowercase : true},
    name : String
});
var FbUsers = mongoose.model('fbs',GithubUserSchema);

四、设置和策略

初始化passport,以便于我们在应用中使用。

1.本地策略

passport.use(new LocalStrategy(function(username, password,done){
    Users.findOne({ username : username},function(err,user){
        if(err) { return done(err); }
        if(!user){
            return done(null, false, { message: 'Incorrect username.' });
        }

        hash( password, user.salt, function (err, hash) {
            if (err) { return done(err); }
            if (hash == user.hash) return done(null, user);
            done(null, false, { message: 'Incorrect password.' });
        });
    });
}));

2.GitHub 用户策略

首先需要到这里申请一个 GitHub 的应用,获取clientIDclientSecret,并确定好 GitHub 授权之后的callbackURL

passport.use(new GithubStrategy({
    clientID: "YOUR ID",
    clientSecret: "YOUR CODE",
    callbackURL: "http://localhost:3000/auth/github/callback"
},function(accessToken, refreshToken, profile, done) {
    FbUsers.findOne({fbId : profile.id}, function(err, oldUser){
        if(oldUser){
            done(null,oldUser);
        }else{
            var newUser = new FbUsers({
                fbId : profile.id ,
                email : profile.emails[0].value,
                name : profile.displayName
            }).save(function(err,newUser){
                if(err) throw err;
                done(null, newUser);
            });
        }
    });
}));

另外一件重要的事情,是设置连载。这样就能在用户的浏览器中建立一个会话的cookie。

passport.serializeUser(function(user, done) {
    done(null, user.id);
});

passport.deserializeUser(function(id, done) {
    FbUsers.findById(id,function(err,user){
        if(err) done(err);
        if(user){
            done(null,user);
        }else{
            Users.findById(id, function(err,user){
                if(err) done(err);
                done(null,user);
            });
        }
    });
});

五、辅助功能函数

就如同前一篇文章一样,需要一些辅助的函数来处理用户登录过程中的问题。这里同样需要。

  • authenticatedOrNot 用于判断用户是否已经登录了。
  • userExist 用于判断用户是否存在。
function authenticatedOrNot(req, res, next){
    if(req.isAuthenticated()){
        next();
    }else{
        res.redirect("/login");
    }
}

function userExist(req, res, next) {
    Users.count({
        username: req.body.username
    }, function (err, count) {
        if (count === 0) {
            next();
        } else {
            // req.session.error = "User Exist"
            res.redirect("/singup");
        }
    });
}

六、路由器

主要需要新增两个地址,一个是请求 GitHub 登录的,一个是 GitHub 登录之后的 callback。

app.get("/auth/github", passport.authenticate("github",{ scope : "email"}));

app.get("/auth/github/callback",
    passport.authenticate("github",{ failureRedirect: '/login'}),
    function(req,res){
        res.render("loggedin", {user : req.user});
    }
);

写了这么多,发现还是直接看源代码来的明白,这里只为了记录:

PassportJS-Authentication

  • 作者「」于 更新本文
  • 文章声明:自由转载-非商用-非衍生-保持署名 | BY-NC-SA
← 用NodeJS完成简单的身份验证 改版:Violet 2 主题来了→
  • 获取每日の能量源
  • ATP