护照-jwt 401 未经授权

Posted

技术标签:

【中文标题】护照-jwt 401 未经授权【英文标题】:passport-jwt 401 Unauthorized 【发布时间】:2018-02-04 10:15:32 【问题描述】:

我正在尝试实现 passport-jwt 身份验证,但在尝试调用端点时总是得到 401 Unauthorized。

这是我的设置

passport.js

var passport = require('passport');
var User = require('../models/user');
var config = require('./auth');
var JwtStrategy = require('passport-jwt').Strategy;
var ExtractJwt = require('passport-jwt').ExtractJwt;
var LocalStrategy = require('passport-local').Strategy;

var localOptions = 
    usernameField: 'email'
;

var localLogin = new LocalStrategy(localOptions, function(email, password, done) 

    User.findOne(
        email: email
    , function(err, user) 
        if (err) 
            return done(err);
        
        if (!user) 
            return done(null, false,  error: 'Login failed. Please try again' );
        

        user.comparePassword(password, function(err, isMatch) 
            if (err) 
                return done(err);
            
            if (!isMatch) 
                return done(null, false,  error: 'Login Failed. Please try again.' );
            

            user.status = 'online';
            user.save(function(err, user) 
                if (err) 
                    return done(err);
                
            );

            return done(null, user);
        );
    );
);

var jwtOptions = 
    jwtFromRequest: ExtractJwt.fromHeader('Authorization'),
    secretOrKey: config.secret
;

var jwtLogin = new JwtStrategy(jwtOptions, function(payload, done) 
    console.log(payload);
    User.findById(payload._id, function(err, user) 
        if (err) 
            return done(err, false);
        
        if (user) 
            done(null, user)
         else 
            done(null, false);
        
    );
);

passport.use(localLogin);
passport.use(jwtLogin);

module.exports = 
    initialize: () => passport.initialize(),
    authenticateJWT: passport.authenticate('jwt',  session: false ),
    authenticateCredentials: passport.authenticate('local',  session: false ),
;

user.js

var express = require('express');
var router = express.Router();
var AuthController = require('../controllers/authentication');
var passportService = require('../config/passport');
var passport = require('passport');

const requireToken = passportService.authenticateJWT;
const requireCredentials = passportService.authenticateCredentials;


router.post('/signup', AuthController.register);
router.post('/signin', requireCredentials, AuthController.login);

router.get('/protected', requireToken function(req, res, next)
res.send(msg:'Success!');
);

module.exports = router;

我已确保我的标头包含:'JWT' + [some token]... 也试过没有'JWT'仍然什么都没有......

我已经检查过其他帖子关于同样的问题,但仍然无法解决。

【问题讨论】:

你确定那是需要的标题吗?通常标头称为 Authorization 和值 Bearer mytoken 根据文档npmjs.com/package/passport-jwt,这似乎是提供令牌的众多方法之一。我试过从体内提取它,但仍然没有结果。同样在这些帖子中:***.com/questions/43091021/…***.com/questions/35528377/… 人们似乎也在这样做。 【参考方案1】:

简短 旧版'JWT ' + [some token]

版本 0.4.0'bearer ' + [some token]

示例 所以当你现在发送令牌时是这样的: 旧版res.json ( success: true, token: 'JWT ' + token )

版本 0.4.0res.json ( success: true, token: 'bearer ' + token )

深入 可能还有其他方法可以做到这一点 如果您查看/node_module/passport-jwt/lib/extract_jwt.js 文件,您可以看到有一个名为versionOneCompatibility(options) 的函数

【讨论】:

我用过同样的,但它也不能解决我使用 V4.0.0 的问题,你能详细说明如何添加这个令牌作为响应,或者如果可能的话请创建演示【参考方案2】:

经过数小时的尝试,我终于通过使用ExtractJwt.fromAuthHeaderWithScheme('Bearer') 方法解决了这个问题。由于某种原因,提取器无法使用其他方法获取令牌。

【讨论】:

【参考方案3】:

我遇到了同样的问题,经过研究,我发现了导致此问题的原因。 当您在路线内创建 res.json 时

//Authenticate
router.post('/authenticate', (req, res, next) => 
  const username = req.body.username;
  const password = req.body.password;

  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) 
        const token = jwt.sign(user.toJSON(), config.secret, 
          expiresIn: 604800 // 1 week
        );
        res.json(
          success: true,
          token: 'jwt ' + token, //Here you have to put space after name inside quotes
          user: 
            id: user._id,
            name: user.name,
            username: user.username,
            email: user.email
          
        );
       else 
        return res.json(
          success: false,
          msg: 'Wrong password'
        );
      
    );
  );
);

在token里面:'jwt'+token,在jwt这个名字后面放一个空格很重要,还有你放在''引号里面的名字你必须把这个名字放在你的里面

var opts = ;
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('jwt');//Here you have to put the same name inside quotes '' like you put inside token but without space after name
opts.secretOrKey = config.secret;
passport.use(new JwtStrategy(opts, function(jwt_payload, done) 
    console.log(jwt_payload);
    User.findOne(
        id: jwt_payload.sub
    , function(err, user) 
        if (err) 
            return done(err, false);
        

        if (user) 
            return done(null, user);
         else 
            return done(null, false);
        
    );
));

这两个要匹配,不管你放jwt还是jwt或者bearer或者其他什么,重要的是它们必须匹配,并且在创建token时必须有空格:'name '。

【讨论】:

以上是关于护照-jwt 401 未经授权的主要内容,如果未能解决你的问题,请参考以下文章

护照-jwt 总是返回 401 未授权

Laravel 护照 oauth 路线总是返回 401 未经授权

护照-jwt sequelize 401 总是

在内部生成 laravel 护照令牌。 401错误未经授权

laravel 6护照中未经授权的401错误

在 Laravel 护照、vueJS 和 Axios 中获得未经授权的 401