护照认证回调不调用护照中间件

Posted

技术标签:

【中文标题】护照认证回调不调用护照中间件【英文标题】:passport authentication callback not calling passport middleware 【发布时间】:2017-10-05 09:59:06 【问题描述】:

我正在尝试通过使用带有护照 JwtStrategy 的 JSON Web 令牌来测试对特定路由的 GET 请求是否受到保护;但是,我的server.js 文件中的passport.use 中间件函数似乎没有执行。我在那里的 console.log 永远不会出现在我的 shell/终端中。我的登录路线有效,但配置文件路线无效。我正在使用邮递员,我在 GET 方法中输入了http://localhost:3000/profile,在Headers 选项卡中,我为密钥和值选择了授权,我复制并粘贴了长 JSON Web 令牌字符串,但它一直说未经授权。那是因为我的 passport.use 函数永远不会被执行。

//Server.js 文件

var JwtStrategy = require("passport-jwt").Strategy;
var ExtractJwt = require("passport-jwt").ExtractJwt;

var User = require("../models/user");
var config = require('./secret');

app.use(passport.initialize());
app.use(passport.session());

let options = ;
//pass token back and forth
options.jwtFromRequest = ExtractJwt.fromAuthHeader();
options.secretOrKey = config;
passport.use(new JwtStrategy(options, (jwt_payload, done) => 
  *******************************************
  //this console log doesn't show up in shell which makes be believe its never getting here
  *******************************************
  console.log("JWT PAYLOAD", jwt_payload)
  User.getUserById(jwt_payload._id, (err, user) => 
    if(err)
      return done(err, false);
    

    if(user) //null for error
      return done(null, user);
    else
      return done(null, false);
    
  );
));

//调用passport.authenticate回调的路由文件

var passport = require('passport');
var jwt = require('jsonwebtoken');
var secret = require('../config/secret')

var User = require('../models/user');

router.post('/login', (req, res) => 
    var username = req.body.username;
    var password = req.body.password;
    console.log("SECRET2", secret);
    console.log("SECRET", secret.secret);
    User.getUserByUsername(username, (err, user) => 
        if(err)
            throw err;
        
        if(!user)
            return res.json( success: false, msg: "User not found");
        

        User.comparePassword(password, user.password, (err, isMatch) => 
            if(err)
                throw err;
            
            if(isMatch)
                var token = jwt.sign(user, secret.secret, 
                    expiresIn: 604800 //1 week in seconds, token expires and requires to log back in
                );

                console.log('TOKEN IN LOGIN ROUTE', token)

                res.json(
                    //tokens are then stored in local storage or cookie
                    success: true,
                    token: 'JWT ' + token,
                    user: 
                        id: user._id,
                        name: user.name,
                        username: user.username,
                        email: user.email
                    
                );
            else
                return res.json( success: false, msg: "Incorrect password");
            
        );
    );
);

router.get('/profile', passport.authenticate('jwt', session:false), (req, res) => 
    res.json(user: req.user);
);

//用户模型

var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');

var Schema = mongoose.Schema;

var UserSchema = new Schema(
  name: 
    type: String,
    trim: true,
    required: "First Name is Required"
  ,
  email: 
    type: String,
    required: true
  ,
  username: 
    type: String,
    required: true
  ,
  password: 
    type: String,
    required: true
  
);

var User = mongoose.model("User", UserSchema);

module.exports = User;

//Alternate syntax for exporting Schema
// var User = module.exports = mongoose.model("User", UserSchema);

module.exports.getUserById = function(id, callback)
    User.findById(id, callback);


module.exports.getUserByUsername = function(username, callback)
    var query =  username: username 
    User.findOne(query, callback);


//Custom User model function that will take in the newUser object and hash the password.
module.exports.addUser = function(newUser, callback)
    bcrypt.genSalt(10, (err, salt) => 
        bcrypt.hash(newUser.password, salt, (err, hash) => 
            if(err)
                throw err
            

            newUser.password = hash;
            newUser.save(callback);
        );
    );


module.exports.comparePassword = function(password, hash, callback)
    bcrypt.compare(password, hash, (err, isMatch) => 
        if(err)
            throw err
        
        callback(null, isMatch);
    );

更新: 我尝试在“JWT”之后为邮递员中的授权值添加一个空格,但它仍然不起作用,并且控制台日志没有显示。是不是因为我没有将我在server.js 中定义的passport.use 导出或链接到我的路由文件中的 GET '/profile' 路由?

更新 2:添加模型和登录路径

【问题讨论】:

Authorization 标头的值必须如下所示:JWT the-actual-token。看here。 你的意思是当我在邮递员上测试 GET 路由到配置文件时?我将类型设置为授权,并将值设置为我粘贴的整个 jwt 令牌。除非我需要那个 JWT 空间然后是令牌。但我不确定这是不是问题,因为 Authenticate (passport.use) 方法似乎永远不会被调用,因为控制台日志永远不会显示。 是的,您需要在值中为令牌添加前缀“JWT-space”。就像我链接到的文档中所说的那样:github.com/themikenicholson/… 我的猜测是该策略永远不会被调用,因为Authorization 标头是“无效的”。 您正在使用secret.secret 生成令牌,但在策略选项中,您使用的是secret,这似乎不正确。顺便说一句:expiresIn 应该以毫秒为单位,而不是秒(现在设置为 10 分钟后过期),严格来说,JWT 不应该是令牌的一部分。 使用这些 id 的客户端(在 URL 或其他方式)来识别用户是很常见的,所以这没什么大不了的。 【参考方案1】:

也许有必要包含更多代码才能看到您的问题,但该策略似乎没有正确导出。创建新策略时,您可以在入口点中包含一个“别名”以使用它:

passport.use('local-login', new JwtStrategy(options, (jwt_payload, done) => 
    ....


router.get('/profile', passport.authenticate('local-login', session:false), (req, res) => 
    res.json(user: req.user);
);

【讨论】:

以上是关于护照认证回调不调用护照中间件的主要内容,如果未能解决你的问题,请参考以下文章

护照中间件不运行

护照认证回调挂起

护照身份验证不起作用。从未调用过的 Passport.serializeUser 和 passport.deserializeUser 会被调用

Laravel 护照公共 api 路线

javascript 护照 - 中间件持票人

护照认证失败导致重定向循环