【问题标题】:Getting 401 unauthorized status while authorizing jwt token using passport-jwt使用 passport-jwt 授权 jwt 令牌时获取 401 未授权状态
【发布时间】:2017-08-22 19:03:35
【问题描述】:

成功登录后,我得到了 jwt 令牌,现在要访问受限制的 api,我正在发送授权标头,但我总是得到 ​​p>

401 未经授权

我已经提到了这个Authenticating node API with passport-jwt 在这里提出的问题,但没有帮助我,

这是我调用的用于从受限 api 访问数据的函数

check() {
    console.log(this.token);
    var headers = new Headers();
    headers.append('Content-Type', 'application/json');
    headers.append("Authorization", "Bearer" +  this.token);
    let url = this.authenticationEndPoint + 'random';
    this.checkauth(url, headers).subscribe(
        data => {
            console.log(data);
        },
        error => {
            console.log("error");
        }
    );
}

checkauth(url:string, header:any): Observable<any> {

    return this.http.get(url, header)
            .map(this.extractData)
            .catch(this.handleError);
}
private extractData(res: Response) {
    let body = res;
    return body || {};
}

在我的 nodeJs 服务器上,这里是发送 jwt 令牌的登录代码:

app.post('/login_mobile', function(req, res) {
    if(!(req.body.email && req.body.passpord)) {
        user.findOne({'local.email' : req.body.email}, function(err, user) {
            if (err) { return done(err);}

            if (!user) {
                return res.json(200, "email is wrong");
            }
            if(!user.validPassword(req.body.password)) {
                return res.json(200, "wrong password");
            }
            var token = jwt.encode(user, configAuth.secret);
            return res.json(200, { user: user, jwtToken: token });
        });
    }
    else {
        res.send("no credentials provided");
    }
});

响应受限 api 请求的代码

app.get('/random', passport.authenticate('jwt', { session: false }),
    function(req, res) {
        res.send("success");
    });

这是我用来验证用户身份的护照策略,但奇怪的是它甚至没有打印 here 仍然发送 401 状态。

var opts = {};
opts.secretOrKey = configAuth.secret;
opts.jwtFromRequest = ExtractJwt.fromAuthHeader();
passport.use(new JwtStrategy(opts, function(jwt_payload, done){
    console.log("here");
    console.log(jwt_payload);
    User.findOne({_id: jwt_payload._id}, function(err, found_user) {
        if (err) {
            return done(err, false);
        }
        if(found_user !== null) {
            res.send("finally");
        }
        else {
            res.send("authentication failed");
        }
        return found_user ? done(null, found_user) : done(null, false);
    })
}));

如果有人可以指出我的错误。

【问题讨论】:

    标签: node.js passport.js


    【解决方案1】:

    更新:此答案使用ExtractJwt.fromAuthHeader,即now deprecated。已更新为使用ExtractJwt.fromAuthHeaderWithScheme('jwt')

    我很头疼,在环顾了几个小时后才解决了这个问题。

    答案和这里的类似:

    Authenticating node API with passport-jwt

    这里:

    passport local strategy not getting called

    使调试变得如此困难的原因在于,如果策略没有得到预期的信息,甚至不会运行。在后者中,LocalStrategy 验证回调没有被启动,因为它没有收到用户名和密码。

    在我的情况下,可能与您的情况相同,JWT 令牌未在标头中以正确的格式提供。这是因为,在成功登录后,我返回了这样的令牌:

    res.status(200).json({
        token: `JWT${generateToken(userInfo)}`,
        user: userInfo,
    });
    

    什么时候我应该这样做:

    res.status(200).json({
        token: `JWT ${generateToken(userInfo)}`,
        user: userInfo,
    });
    

    查看 JWT 后面的空格。因此,我的 jwtStrategy 函数在期待 JWT x759ghv... 时收到了类似 JWTx759ghv... 的身份验证令牌。

    如果 Passport 对此发出警告会很方便!

    这是我的完整设置,以防有任何帮助:

    // passportService.js
    
    const passport = require('passport');
    const JwtStrategy = require('passport-jwt').Strategy;
    const ExtractJwt = require('passport-jwt').ExtractJwt;
    const LocalStrategy = require('passport-local');
    
    const User = require('../models/User');
    const config = require('../config');
    
    /**
    * Local Login Strategy
    */
    
    const localOptions = {
        usernameField: 'email',
    };
    
    const localLogin = new LocalStrategy(localOptions, (email, password, done) => {
        console.log('Using Local strategy');
        console.log(email, password);
        User.findOne({ email }, (err, user) => {
            if (err) { return done(err); }
            if (!user) { return done(null, false, { message: 'Your login details could not be verified. Please try again.' }); }
    
            user.comparePassword(password, (passwordErr, isMatch) => {
                if (passwordErr) { return done(passwordErr); }
                if (!isMatch) { return done(null, false, { message: 'Your login details could not be verified. Please try again.' }); }
                return done(null, user);
            });
            return false;
        });
    });
    
    
    /**
    * JWT Strategy
    */
    
    const jwtOptions = {
        /*
         * Deprecated: fromAuthHeader() - see update above
        jwtFromRequest: ExtractJwt.fromAuthHeader(),
         */
    
        jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme("jwt"),
        secretOrKey: config.auth.passport.key,
    };
    
    console.log(jwtOptions);
    
    const jwtLogin = new JwtStrategy(jwtOptions, (payload, done) => {
        User.findById(payload._id, (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 }),
    };
    

    然后,在我的路线中使用:

    // ... after of the other Express app initialization
    
    const passportService = require('./services/passport');
    const AuthenticationController = require('./controllers/Authentication');
    
    const requireToken = passportService.authenticateJWT;
    const requireCredentials = passportService.authenticateCredentials;
    
    app.use(passportService.initialize());
    
    authRoutes.post('/register', AuthenticationController.register);
    apiRoutes.get('/protected', requireToken, AuthenticationController.login);
    authRoutes.post('/login', requireCredentials, AuthenticationController.login);
    

    如果您仍然遇到问题,请在调用策略之前尝试运行一小段中间件,以确保您发送的标头格式正确:

    apiRoutes.get('/protected', (req, res) => {
      console.log(req.headers);
    }, requireToken, AuthenticationController.login);
    

    【讨论】:

    • 我收到 TypeError:ExtractJwt.fromAuthHeader 不是函数
    • @ggnoredo,看起来这个功能已经被弃用了。我已经更新了我上面的评论——多纳托在这个帖子中的回答有一个类似的解决方案。
    【解决方案2】:

    我修复了一个类似的问题替换:

    jwtFromRequest: ExtractJwt.fromAuthHeader(),
    

    与:

    jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
    

    【讨论】:

      猜你喜欢
      • 2017-11-12
      • 2017-01-12
      • 2018-02-02
      • 2018-06-05
      • 2020-10-20
      • 2018-06-06
      • 2021-09-21
      • 2018-11-05
      • 1970-01-01
      相关资源
      最近更新 更多