代码之家  ›  专栏  ›  技术社区  ›  PatrikJ

PassportJS对用户进行身份验证,但在后续请求中返回401 Unauthorized

  •  0
  • PatrikJ  · 技术社区  · 6 年前

    我正在用NodeJS写我的第一份申请书,所以请耐心听我说。我已经成功地向我们的Active directory验证了一个用户,我可以看到connect.sid cookie被设置并用于后续请求。

    总结一下:

    1. 用户在发布凭据/登录后已成功通过身份验证。
    2. 认证成功后,用户将被重定向到“/”。

    有什么好主意吗。代码如下。

    const express = require('express');
    var bodyParser = require('body-parser');
    var session = require('express-session');
    var passport = require('passport')
    var ActiveDirectoryStrategy = require('passport-activedirectory')
    
    // Setup the authentication strategy
    passport.use(new ActiveDirectoryStrategy({
        integrated: false,
        ldap: {
            url: 'ldap://myad.company.com',
            baseDN: 'DC=domain,DC=company,DC=com',
            username: 'user',
            password: 'password'
        }
    }, function (profile, ad, done) {
        ad.isUserMemberOf(profile._json.dn, 'Group', function (err, isMember) {
            if (err) return done(err)
            return done(null, profile)
        })
    }));
    
    passport.serializeUser(function(user, done) {
        done(null, JSON.stringify(user));
      });
    
    passport.deserializeUser(function(user, done) {
        done(null, JSON.parse(user));
    });
    
    const app = express();
    
    app.use(bodyParser.urlencoded({extended: true}));
    app.use(session(
        { secret: "password" }
    ));
    app.use(passport.initialize());
    app.use(passport.session());
    
    // For debugging purposes
    app.use(function (req, res, next) {
        console.log(req)
        next()
    })
    
    // The login page posts a form containing user and password
    app.get("/login", (req, res) => {
        res.sendFile(__dirname + '/public/index.html');
    })
    
    // Handler for the login page. Receives user and password and redirects the user to /
    app.post('/login', 
        passport.authenticate('ActiveDirectory', {
                failWithError: true,
                successRedirect: "/",
                failureRedirect: "/login"
            }
        ), function(req, res) {
            res.json(req.user)
        }, function (err) {
            res.status(401).send('Not Authenticated')
        }
    )
    
    // This is where the issue happens. The page returns "Unauthorized".
    // Using console.log(req) shows that the user property has been set to the req object.
    // However, for some reason it still fails.
    app.get('/',
        passport.authenticate('ActiveDirectory', {
                failWithError: true,
            }
        ), function(req, res) {
            res.send("test")
    }, function (err) {
        res.status(401).send('Not Authenticated')
    })
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   PatrikJ    6 年前

    发现我做错了什么!

    .authenticate方法仅用于验证凭据,而不用于验证会话。

    因此:

    app.get('/',
        passport.authenticate('ActiveDirectory', {
                failWithError: true,
            }
        ), function(req, res) {
            res.send("test")
    }, function (err) {
        res.status(401).send('Not Authenticated')
    })
    

    应该变成:

    app.get('/', function(req, res, next) {
        // This is verifying that the user part has been populated,
        // which means that the user has been authenticated.
        if (req.user) {
            res.send('Returning with some text');
        } else {
            // If the user property does no exist, redirect to /login
            res.redirect('/login');
        }
      });
    

    我改变的另一件事是序列化/反序列化函数:

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

    这将删除冗余的序列化/反序列化。

    这些文章真的帮助我了解了流程:

    希望它能帮助别人!

    /帕特里克