Passport.js:身份验证后如何访问用户对象?

44

我正在使用Passport.js来实现用户名和密码的用户登录功能。我基本上是在使用Passport网站提供的示例代码。以下是我的代码中相关的部分(我认为):

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

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

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

passport.use(new LocalStrategy(function(username, password, done) {
    User.findOne({ username: username }, function(err, user) {
        if (err) {
            return done(err);
        }
        if (!user) {
            return done(null, false, { message: 'Incorrect username.' });
        }
        if (!user.validPassword(password)) {
            return done(null, false, { message: 'Incorrect password.' });
        }
        return done(null, user);
        });
    }
));

app.post('/login',
    passport.authenticate('local', { failureRedirect: '/login/fail', failureFlash: false }),
    function(req, res) {
        // Successful login
        //console.log("Login successful.");
        // I CAN ACCESS req.user here
});

这似乎正确登录。但是,我希望能够在代码的其他部分访问登录用户的信息,例如:

app.get('/test', function(req, res){
    // How can I get the user's login info here?
    console.log(req.user);  // <------ this outputs undefined
});

我已经在SO上查找了其他问题,但我不确定我在这里做错了什么。谢谢!

8个回答

74

虽然来晚了,但我在谷歌上搜索后找到了这个未被回答的问题。

请求中将会有一个req.user对象,你可以对其进行操作。

路由如下:

app.get('/api/portfolio', passport.authenticate('jwt', { session: false }), stocks.buy);

这样的控制器:

buy: function(req, res) {
      console.log(req.body);
      //res.json({lel: req.user._id});
      res.json({lel: req.user});
    }

9
这应该是正确答案,因为它更直接地解决了问题... 对于无状态的REST API,这是正确的方法... - Żabojad
7
如果登录后,req.user 出现未定义的情况,该怎么办? - Adrienne
2
我有这个,但仍然有问题,你有什么想法吗? - Eddie Jaoude

13

关于护照文档的参考,用户对象包含在req.user中。见下方。

    app.post('/login',
      passport.authenticate('local'),function(req, res) {
       // If this function gets called, authentication was successful.
       // `req.user` contains the authenticated user.
       res.redirect('/users/' + req.user.username);
     });

那样,您可以从重定向到的页面访问用户对象。
如果遇到困难,您可以参考我的Github项目,我在其中清楚地实现了它。

这正是我一直在寻找的!我从未想到过如何实际访问req.user,而这篇文章完美地总结了它。谢谢! - Rahul
护照文件链接已过期,请编辑您的答案。 - Thecave3
1
已更新!感谢 @Thecave3 - L.T

2

我对JavaScript还比较陌生,但从教程中了解到,您需要首先实现一些会话中间件,正如250R所指示的那样。

const session = require('express-session')
const app = express()

app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())

let sess = {
    genid: (req) => {
        console.log('Inside the session middleware')
        console.log(req.sessionID)
        return uuid()
    },
    store: new FileStore(),
    secret: 'keyboard cat', // password from environment
    resave: false,
    rolling: true,
    saveUninitialized: true,
    cookie: {
        HttpOnly: true,
        maxAge: 30 * 60 * 1000 // 30 minutes
    }
}

app.use(session(sess))

// call passport after configuring the session with express-session
// as it rides on top of it
app.use(passport.initialize())
app.use(passport.session())

// then you will be able to use the 'user' property on the `req` object
// containing all your session details
app.get('/test', function (req, res) {
    console.log(req.user)
})

2

res.render 可以接受一个可选参数,该参数是一个包含视图本地变量的对象。

如果您使用passport并已经验证了用户,则req.user 包含已验证的用户。

// app.js
app.get('/dashboard', (req, res) => {
  res.render('./dashboard', { user: req.user })
})

// index.ejs
<%= user.name %>

1
您可以按照以下方式定义您的路由。
router.post('/login',
passport.authenticate('local' , {failureRedirect:'/login', failureFlash: true}),
function(req, res) {
   res.redirect('/home?' + req.user.username);
});

在上面的代码片段中,您可以访问并通过"req.user.field_name"将用户对象的任何字段传递到要重定向的页面。这里需要注意的一件事是,要重定向到的页面的基本URL应该后跟一个问号。

0

对于使用Next.js的人的解决方案:

奇怪的是,—> 解决方案 <— 来自于next-connect最近删除的README部分,但它的效果非常好。如果您使用的是纯JS,则可以忽略typescript部分。

关键部分是./src/pages/index中的getServerSideProps函数(或者您想要获取用户对象的任何文件)。

// —> ./src/authMiddleware.ts
// You'll need your session, initialised passport and passport with the session,
// so here's an example of how we've got ours setup, yours may be different

//
// Create the Passport middleware for SAML auth.
//
export const ppinit = passport.initialize();

//
// Set up Passport to work with expressjs sessions.
//
export const ppsession = passport.session();

//
// Set up expressjs session handling middleware
//
export const sess = session({
  secret: process.env.sessionSecret as string,
  resave: true,
  saveUninitialized: true,
  store: sessionStore,
});

// —> ./src/pages/index.ts

// update your user interface to match yours
export interface User {
  id: string;
  name: string;
}

interface ExtendedReq extends NextApiRequest {
  user: User;
}

interface ServerProps {
  req: ExtendedReq;
  res: NextApiResponse;
}

interface ServerPropsReturn {
  user?: User;
}

export async function getServerSideProps({ req, res }: ServerProps) {
  const middleware = nc()
    .use(sess, ppinit, ppsession)
    .get((req: Express.Request, res: NextApiResponse, next) => {
      next();
    });

  try {
    await middleware.run(req, res);
  } catch (e) {
    // handle the error
  }

  const props: ServerPropsReturn = {};
  if (req.user) props.user = req.user;
  return { props };
}

interface Props {
  user?: User;
}

//
// A trivial Home page - it should show minimal info if the user is not authenticated.
//
export default function Home({ user }: Props) {
  return (
    <>
      <Head>
        <title>My app</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main>
        <h1>Welcome to My App {user?.name}</h1>
      </main>
    </>
  );
}

0

虽然有点晚了,但这对我有效。

在你的 app.js 中使用这个。

app.use(function(req,res,next){
  res.locals.currentUser = req.user;
  next();
})

在客户端获取当前用户详细信息,例如ejs。
<%= locals.currentUser.[parameter like name || email] %>

-3

在注册passport中间件之前,您需要确保注册一个中间件来填充req.session

例如,以下示例使用express cookieSession中间件

app.configure(function() {

  // some code ...

  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.cookieSession()); // Express cookie session middleware 
  app.use(passport.initialize());   // passport initialize middleware
  app.use(passport.session());      // passport session middleware 

  // more code ...

});

71
这个支持设置代码并未说明如何最终将用户从会话中获取出来。 - Jon Davis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接