发布于 2026-01-06 6 阅读
0

什么是 PassportJS?如何集成它?

什么是 PassportJS?如何集成它?

根据官方定义:

Passport 是 Node.js 的身份验证中间件。

Passport 具有极高的灵活性和模块化特性,可以毫不突兀地集成到任何基于 Express 的 Web 应用程序中。

一套全面的策略支持使用用户名和密码、Facebook、Twitter 等进行身份验证。

基本上,PassportJS 为我们管理会话用户,并为我们提供了在应用程序中集成登录/注册选项时可以使用的许多策略。

我们来看看如何将其整合起来。

集成 PassportJS

让我们从应用程序的基础架构开始:

const express = require('express')

const app = express()
const port = 3000

app.listen(port, () => console.log(`App listening on port ${port}!`))

现在我们可以开始配置Passport了。

我们需要配置会话中间件、cookie解析器和body解析器:

const cookieParser = require('cookie-parser')
const bodyParser = require('body-parser')
const expressSession = require('express-session')
const passport = require('passport')

...

app.use(cookieParser())          // 1
app.use(bodyParser.json())       // 2
app.use(bodyParser.urlencoded({
  extended: true,
}))                              // 3
app.use(expressSession({
  secret: '5om35ecr37',
  resave: false,
  saveUninitialized: false,
}))                              // 4
app.use(passport.initialize())   // 5
app.use(passport.session())      // 6

让我们来看一下并解释每一行代码的作用:

  1. 中间件解析 Cookie 标头值,并将 cookies 属性添加到请求对象中,该请求对象包含所有按 cookie 名称键分组的 cookie。
  2. 将请求体解析为 JSON 数据,并将其添加到请求对象的 body 属性中。
  3. 增加了对解析 URL 格式请求体的支持。
  4. 用于生成会话 cookie 并将其与服务器端存储的数据(即已登录用户)进行匹配的中间件。
  5. 初始化 Passport 核心,该核心运行并管理策略。
  6. 添加对会话中用户数据管理的支持。

增加本地化策略

现在中间件都配置好了,我们可以向应用程序中添加策略了。

在这种情况下,这将是一项本地化策略。

首先,我们需要安装选定的策略:

npm install passport-local

或者:

yarn add passport-local

现在我们可以进行配置了。

为了简化本教程,我将在回调函数中返回静态用户对象:

const userStore = {
  findByUsername: () => ({
    id: 1,
    name: 'Test User',
    username: 'testuser',
    validatePassword: () => true
  })
}

passport.use(new LocalStrategy(
  (username, password, done) => {
    const user = userStore.findByUsername(username)

    // User does not exist in our database or password was invalid
    if (!user || !user.validatePassword(password)) {
      return done(null, false)
    }
    // If user was found and password is valid we can return user object
    // in callback
    return done(null, user)
  }
))

就这样!

我们的登录表单逻辑已准备就绪。

会话序列化和反序列化

当我们使用Passport并启用会话支持时,我们必须实现两个回调函数,Passport 将使用这两个回调函数来序列化和反序列化用户。

当用户被保存到会话中时,将调用 Serialize 回调函数

我们将使用用户 ID,以便稍后在数据库中找到该用户。

passport.serializeUser((user, done) => {
  done(null, user.id)
})

反序列化回调用于根据存储在 cookie 中的数据在数据库中查找用户。

在本例中,存储在 cookie 中的数据是用户 ID。

const userStore = {
  ...,
  findUserById: userId => ({
    id: 1,
    name: 'Test User',
    username: 'testuser',
    validatePassword: () => true
  })
}

passport.deserializeUser((userId, done) => {
  // Find user in database by id from session
  const user = userStore.findUserById(userId)


  // If user was not found throw an error
  if (!user) {
    done('unathorized')
    return
  }


  // If user was found return it via callback, this user object will be  
  // available in  request object as user property
  done(null, user)
})

添加登录表单

现在我们可以给应用添加登录表单了。

为此,我们来定义一个简单的HTML表单。

<html>
<head>
  <title>Awesome login form</title>
</head>
<body>
  <form action="/" method="POST">
    <label for="username">
      Username:
    </label>
    <input name="username" id="username" />
    <label for="password">
      Password:
    </label>
    <input type="password" name="password" id="password" />
    <button type="submit">
      Login
    </button>
  </form>
</body>
</html>

并将此 HTML 文件返回到我们应用程序的根 URL:

const path = require('path')

app.get('/', (request, response) => {
  response.sendFile(path.resolve('./login.html'))
})

现在我们需要定义处理表单 POST 请求的路径:

// This will print “Logged in!” text after successful login
app.post(
  '/',
  passport.authenticate('local'),
  (request, response) => {
    response.send('Logged in!')
  }
)

让我们回到根 URL 处理程序,如果用户已登录,则返回不同的视图。

首先,我们需要为登录视图创建 HTML 文件:

<html>
<head>
  <title>Awesome logged in view</title>
</head>
<body>
  <a href='/logout'>Logout</a>
</body>
</html>

并将我们的根 URL 处理程序修改如下:

// This will redirect user back to root url after logging in
app.post('/', passport.authenticate('local', { successRedirect: '/' }))

app.get('/', (request, response) => {
  const viewPath = request.isAuthenticated()
    ? './loggedIn.html'
    : './login.html'

  response.sendFile(path.resolve(viewPath))
})

如您所见,我在登录视图中定义了“/logout”URL,因此我们也必须处理该URL。

点击此链接将注销用户并将其重定向回登录表单。

app.get('/logout', (request, response) => {
  request.logOut()

  response.redirect('/')
})

概括

如果你使用NodeJS,PassportJS是一个很棒的身份验证工具,你可以轻松地针对不同的策略进行定制。

请告诉我你的想法!

文章来源:https://dev.to/pagepro_agency/what-is-passportjs-and-how-to-integrate-it-31io