护照:允许注册姓名和电子邮件地址?(地方战略)

For*_*vin 16 javascript node.js passport-local passport.js

有没有办法允许用户使用他的密码,电子邮件和姓名注册本地策略?
我在网上找到的每个例子都只使用名称/密码或电子邮件/密码.

我还搜索了整个护照文档,但该文档根本没用.这只是一个充满例子的臃肿网站.
我只需要一份护照使用的函数,类和变量列表,并解释它们和它们的每个参数的作用.每个好的图书馆都有这样的东西,为什么我找不到护照?

以下是我的代码的关键部分:

passport.use('local-signup', new LocalStrategy({
    usernameField: 'email',
    passwordField: 'password',
    //are there other options?
    //emailField did not seem to do anything
    passReqToCallback: true // allows us to pass in the req from our route (lets us check if a user is logged in or not)
},
function(req, email, password, done) {
    //check if email not already in database
        //create new user using "email" and "password"
        //I want an additional parameter here "name"
}));
Run Code Online (Sandbox Code Playgroud)

护照真的那么有限吗?必须有办法做到这一点,对吧?

Eug*_*kov 23

您可能会有点困惑,但护照不会实施注册方法.它只是授权库.所以你必须自己处理这个用例.

首先,创建负责注册和检查的路线:

signup: function (req, res) {
  User
    .findOne({
      or: [{username: req.param('username')}, {email: req.param('email')}]
    })
    .then(function(user) {
      if (user) return {message: 'User already exists'};          
      return User.create(req.allParams());
    })
    .then(res.ok)
    .catch(res.negotiate);
}
Run Code Online (Sandbox Code Playgroud)

上面的示例基于Sails框架,但您可以适应它而不会出现问题.

下一步是包括护照本地策略.

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;

var LOCAL_STRATEGY_CONFIG = {
  usernameField: 'email',
  passwordField: 'password',
  session: false,
  passReqToCallback: true
};

function _onLocalStrategyAuth(req, email, password, next) {
  User
    .findOne(or: [{email: email}, {username: email}])
    .then(function (user) {
      if (!user) return next(null, null, {
        code: 'E_USER_NOT_FOUND',
        message: email + ' is not found',
        status: 401
      });

      if (!HashService.bcrypt.compareSync(password, user.password)) return next(null, null, {
        code: 'E_WRONG_PASSWORD',
        message: 'Password is wrong',
        status: 401
      });

      return next(null, user, {});
    })
    .catch(next);
}

passport.use(new LocalStrategy(LOCAL_STRATEGY_CONFIG), _onLocalStrategyAuth));
Run Code Online (Sandbox Code Playgroud)

我们现在只有登录任务.这很简单.

signin: function(req, res) {
  passport.authenticate('local', function(error, user, info) {
    if (error || !user) return res.negotiate(Object.assign(error, info));
    return res.ok(user);
  })(req, res);
}
Run Code Online (Sandbox Code Playgroud)

这种方式更适合护照,对我来说很有用.


Fat*_*tie 6

说你有这个

app.post('/login', urlencodedParser,
    // so, user has been to /loginpage and clicked submit.
    // /loginpage has a post form that goes to "/login".
    // hence you arrive here.
    passport.authenticate('my-simple-login-strategy', {
        failureRedirect: '/loginagain'
    }),
        function(req, res) {
            console.log("you are in ............")
            res.redirect('/stuff');
    });
Run Code Online (Sandbox Code Playgroud)

请注意,.authenticate具有显式标记。

标签是 'my-simple-login-strategy'

这意味着你有这个......

passport.use(
    'my-simple-login-strategy',
    // !!!!!!!!!!!!!note!!!!!!!!!!, the DEFAULT there (if you have nothing)
    // is 'local'. A good example of defaults being silly :/
    new Strategy(
        STRAT_CONFIG,
        function(email, password, cb) {
           // must return cb(null, false) or cb(null, the_user_struct) or cb(err)
           db.findUserByEmailPass(email, password, function(err, userFoundByDB) {
                if (err) { return cb(err); }
                if (!userFoundByDB) { return cb(null, false); }
                console.log('... ' + JSON.stringify(userFoundByDB) )
                return cb(null, userFoundByDB)
           })
        }
    )
)
Run Code Online (Sandbox Code Playgroud)

!!!!!!请注意,“本地”只是默认标签名称!!!!!!

在 中passport.use,我们总是放入一个明确的标签。如果你这样做就更清楚了。在策略中和app.post何时使用策略中放入显式标签。

这就是我的简单登录策略。

实际的 db.findUserByEmailPass sql 函数是什么?

我们会回到那个!

所以我们有我的简单登录策略

接下来......我们需要 my-simple-createaccount-strategy

请注意,我们仍在偷偷使用passport.authenticate:

所以:

my-simple-createaccount-strategy 策略实际上会创建一个帐户。

然而 .............

你仍然应该返回一个结构。

请注意, my-simple-login-strategy 必须返回一个结构体。

因此, my-simple-createaccount-strategy 也必须以完全相同的方式返回一个结构体。

app.post('/createaccount', urlencodedParser,
    // so, user has been to /createanaccountform and clicked submit,
    // that sends a post to /createaccount. So we are here:
    passport.authenticate('my-simple-createaccount-strategy', {
        failureRedirect: '/loginagain'
    }),
        function(req, res) {
            console.log("you are in ............")
            res.redirect('/stuff');
    });
Run Code Online (Sandbox Code Playgroud)

这是策略…………

passport.use(
    'my-simple-createaccount-strategy',
    new Strategy(
        STRAT_CONFIG,
        function(email, password, cb) {
            // return cb(null, false), or cb(null, the_user_struct) or cb(err)
            db.simpleCreate(email, password, function(err, trueOrFalse) {
                if (err) { return cb(err); }
                if (!trueOrFalse) { return cb(null, false); }
                return cb(null, trueOrFalse)
            })
        }
    )
)
Run Code Online (Sandbox Code Playgroud)

策略几乎相同。但是 db 调用是不同的。

所以现在让我们看看 db 调用。

让我们看看 db 调用!

普通策略的普通 db 调用将如下所示:

exports.findUserByEmailPass = function(email, password, cb) {
    // return the struct or false via the callback
    dc.query(
        'select * from users where email = ? and password = ?',
        [email, password],
        (error, users, fields) => {
            if (error) { throw error } // or something like cb(new Error('blah'));
            cb(null, (users.length == 1) ? users[0] : false)
        })
}
Run Code Online (Sandbox Code Playgroud)

这就是exports.findUserByEmailPass,它由my-simple-login-strategy 使用。

但是对于 my-simple-createaccount-strategy 来说,exports.simpleCreate 呢?

一个简单的玩具版本

  1. 检查用户名是否已经存在 - 如果它已经存在,此时返回 false,然后
  2. 创建它,然后
  3. 实际上只是再次返回记录。

回想一下,(3) 就像在普通的“find”调用中一样。

请记住...... my-simple-createaccount-strategy 策略实际上会创建一个帐户。但是您仍然应该与您的普通身份验证策略 my-simple-login-strategy相同的方式返回一个结构体。

所以exports.simpleCreate 是一个简单的三个调用链:

exports.simpleCreate = function(email, password, cb) {
    // check if exists; insert; re-select and return it
    dc.query(
        'select * from users where email = ?', [email],
        (error, users, fields) => {
            if (error) { throw error } // or something like cb(new Error('blah'));
            if (users.length > 0) {
                return cb(null, false)
            }  
            else {
                return partTwo(email, password, cb)
            }
        })
}

partTwo = function(email, password, cb) {
    dc.query(
        'insert into users (email, password) values (?, ?)', [email, password],
        (error, users, fields) => {
            if (error) { throw error } // or something like cb(new Error('blah'));
            partThree(email, password, cb)
        })
}

partThree = function(email, password, cb) {
    dc.query(
        'select * from users where email = ? and password = ?', [email, password],
        (error, users, fields) => {
            if (error) { throw error } // or something like cb(new Error('blah'));
            cb(null, (users.length == 1) ? users[0] : false)
        })
}
Run Code Online (Sandbox Code Playgroud)

这一切都有效。

但请注意

护照与帐户创建无关

事实上,您根本不必使用策略。

app.post('/createaccount'你可以,如果你愿意,什么都不passport.authenticate做......甚至不要在代码中提到它。根本不要使用身份验证。继续执行插入新用户的 sql 过程,就在 app.post 中。

但是,如果您“巧妙地”使用通行证策略 - 在示例中为 my-simple-createaccount-strategy - 您将获得奖励,即用户会立即通过会话登录,并且一切都以与登录帖子相同的模式运行. 凉爽的。


Mei*_*eir 5

这是对我有用的解决方案,该解决方案基于基于猫鼬的odm,第一部分是护照相关部分,我还将odm的用户部分附加到谁进行密码加密的工作上。

如果我理解您的问题,则希望用户输入他的电子邮件或密码。在这种情况下,修改搜索以尝试两者,即,将提供的用户标识符(在您对findOne(...)的调用中)与用户名或密码匹配。

请注意,我使用bcrypt来避免存储明确的密码,这就是为什么有一种用于测试密码的自定义比较方法的原因。还要注意使用Google Auth的“提示”,“我的系统”同时启用了这两个功能,如果相关,请记住,我可以添加所需的代码。

------------身份验证部分(仅相关片段)-----------

var passport = require('passport'),
LocalStrategy = require('passport-local').Strategy;

passport.serializeUser(function(user, done) {
    // the values returned here will be used to deserializeUser
    // this can be use for further logins
    done(null, {username: user.username, _id: user.id, role: user.role});
});

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


passport.use(new LocalStrategy(function(username, password, done){
    odm.User.findOne({username: username, authType: 'direct'}, function(err, user){
        if(err){
            return done(err, false);
        }
        if(!user){
            return done(null, false);
        }
        if(user.role === 'new'){
            console.log('can not use new user!');
            return done('user not activated yet, please contact admin', false);
        }
        user.comparePassword(password,function(err, isMatch){
            if(err){
                return done(err, false);
            }
            if(isMatch){
                return done(null, user);//{username: username});
            }
            return done(null, false);
        });
    });
}));
app.post('/login',  function(req, res, next){
        passport.authenticate('local', {
            failureRedirect: '/logout?status=login failed'
        }, function(err, user, info){
                if(err){
                    return next(err);
                }
                if(!user){
                    return res.redirect('/login');
                }
                req.logIn(user, function(err){
                    if (req.body.rememberme) {
                        req.session.cookie.maxAge = 30*24*60*60*1000 ;//Rememeber 'me' for 30 days
                    } else {
                        req.session.cookie.expires = false;
                    }
                    var redirect = req.param('redirect') || '/index';
                    res.redirect(redirect);
                });
            }
        )(req, res, next);
    }
);

app.post('/register',function(req, res){
    var user = new odm.User({username: req.body.username, password: req.body.password, email: req.body.email, authType: 'direct'});
    user.save(function(err, user){
        if(err){
            console.log('registration err: ' , err);
        } else {
            res.redirect('/list');
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

---用户/ odm,相关部分----------------

var bcrypt = require('bcrypt-nodejs');

// --------------------- User ------------------------------------------ //
var userSchema = new Schema({
    name: String,
    email: String,
    username: {type: String, required: true, unique: true},
    password: String,
    role: {type: String, required: true, enum: ['new', 'admin', 'user'], default: 'new'},
    authType: {type: String, enum: ['google', 'direct'], required: true}
});

userSchema.pre('save', function (next) {
    var user = this;
    if (!user.isModified('password')) return next();

    console.log('making hash...........');
    bcrypt.genSalt(SALT_WORK_FACTOR, function (err, salt) {
        if (err) return next(err);

        bcrypt.hash(user.password, salt, null, function (err, hash) {
            if (err) return next(err);
            user.password = hash;
            next();
        });
    });
});

userSchema.methods.comparePassword = function (candidatePassword, cb) {
    bcrypt.compare(candidatePassword, this.password, function (err, isMatch) {
        if (err) return cb(err);
        cb(null, isMatch);
    });
};
Run Code Online (Sandbox Code Playgroud)