身份验证是 web 应用程序中至关重要的一部分。在本文中,我们将通过使用 Express.js 构建一个完整的身份验证系统来深入探讨如何有效地实现身份验证。本文包含以下内容:
- 什么是身份验证
- 使用 Passport.js 实现身份验证
- 实现注册和登录功能
- 保护路由
- 使用 JSON Web Tokens 进行令牌身份验证
- 示例代码
什么是身份验证?
身份验证是确认用户是谁的过程。在 web 应用程序中,身份验证通常涉及用户提供凭据(例如用户名和密码),然后将这些凭据与存储在数据库中的用户信息进行比较。如果凭据匹配,用户就可以访问受保护的资源。否则,用户将被拒绝访问。
使用 Passport.js 实现身份验证
Passport.js 是一个流行的 Node.js 身份验证库,它提供了许多不同的身份验证策略,包括本地身份验证、OAuth、OpenID 等。在本文中,我们将使用本地身份验证策略。
要使用 Passport.js,您需要安装 passport
和 passport-local
包。您还需要安装 bcrypt
包来对用户密码进行哈希。
首先,我们需要配置 Passport.js。在您的应用程序的入口文件中,添加以下代码:
-- -------------------- ---- ------- ----- -------- - -------------------- ----- ------------- - ----------------------------------- ----- ------ - ------------------ ---------------- -------------- ----- ------------------ --------- ----- - ----- ---- - ----- -------------- -------- --- -- ------- - ------ ---------- ------- - ----- ------------- - ----- ------------------------ --------------- -- ---------------- - ------ ---------- ------- - ------ ---------- ------ - ---展开代码
在这里,我们定义了一个本地身份验证策略。该策略接受用户名和密码,并使用 User.findOne()
方法在数据库中查找用户。如果找到了用户,则使用 bcrypt.compare()
方法比较密码是否匹配。如果密码匹配,则使用 done()
方法将用户对象传递给下一个处理程序。
接下来,我们需要为 Passport.js 配置序列化和反序列化功能。这些功能用于将用户对象序列化为一个字符串,以便将其存储在 session 中,并在需要时将其反序列化回用户对象。
passport.serializeUser(function(user, done) { done(null, user.id); }); passport.deserializeUser(async function(id, done) { const user = await User.findById(id); done(null, user); });
在这里,我们使用 user.id
将用户对象序列化为字符串,并将其传递给 done()
方法。在反序列化功能中,我们使用 User.findById()
方法通过用户 ID 查找用户对象,并将其传递给 done()
方法。
最后,在您的应用程序中间件中添加以下代码以启用 Passport.js:
app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false })); app.use(passport.initialize()); app.use(passport.session());
在这里,我们使用 express-session
中间件来启用会话。我们还使用 passport.initialize()
和 passport.session()
中间件来启用 Passport.js。
实现注册和登录功能
现在我们已经配置了 Passport.js,让我们来实现注册和登录功能。首先,我们需要创建一个注册页面和一个登录页面。在这里,我们将使用 EJS 模板引擎来渲染这些页面。
-- -------------------- ---- ------- ---- ---- --- ----- ------------- ------------------- ------ ----------- --------------- ------------------ ------ --------------- --------------- ----------------- ------ ------------- ----------- ------- ---- ---- --- ----- ------------- ---------------- ------ ----------- --------------- ------------------ ------ --------------- --------------- ----------------- ------ ------------- ----------- -------展开代码
在这里,我们创建了一个注册表单和一个登录表单。这些表单将向 /register
和 /login
路由提交数据。
接下来,让我们来实现 /register
和 /login
路由。在这里,我们将使用 Passport.js 的 passport.authenticate()
方法来处理身份验证。
-- -------------------- ---- ------- -- ---- --------------------- ----- ----- ---- -- - ----- - --------- -------- - - --------- ----- -------------- - ----- --------------------- ---- ----- ---- - --- ------ --------- --------- -------------- --- ----- ------------ --------------- ----- -- - -- ----- - ------ ---------- - ------------------ --- --- -- ---- ------------------ ------------------------------ - ---------------- ---- ---------------- -------- ----展开代码
在这里,我们使用 bcrypt.hash()
方法将用户密码哈希,并将其存储在数据库中。在注册完成后,我们使用 req.login()
方法将用户对象存储在会话中,并将用户重定向到主页。
在登录路由中,我们使用 passport.authenticate()
方法来处理身份验证。如果身份验证成功,则用户将重定向到主页。否则,用户将重定向到登录页面。
保护路由
现在,我们已经实现了注册和登录功能。让我们来看看如何保护受保护的路由。在这里,我们将使用 Passport.js 的 req.isAuthenticated()
方法来检查用户是否已通过身份验证。
// 受保护的路由 app.get('/profile', (req, res) => { if (req.isAuthenticated()) { res.render('profile', { user: req.user }); } else { res.redirect('/login'); } });
在这里,我们检查用户是否已通过身份验证。如果用户已通过身份验证,则将用户对象传递给 profile
模板。否则,用户将被重定向到登录页面。
使用 JSON Web Tokens 进行令牌身份验证
使用 Passport.js 进行身份验证是一种流行的方法,但它并不是唯一的方法。另一种流行的方法是使用 JSON Web Tokens(JWT)进行令牌身份验证。
JWT 是一种用于安全通信的开放标准。它定义了一种用于在双方之间安全传输信息的方法。JWT 由三部分组成:头部、载荷和签名。头部和载荷是 JSON 对象,签名是使用密钥和头部和载荷的组合计算出来的值。
在身份验证过程中,服务器将生成一个 JWT 并将其发送给客户端。客户端将在每个请求中将 JWT 发送回服务器。服务器将验证 JWT 的签名,并使用载荷中的信息来确认用户的身份。
要使用 JWT 进行令牌身份验证,您需要安装 jsonwebtoken
包。接下来,让我们来看看如何生成和验证 JWT。
-- -------------------- ---- ------- ----- --- - ------------------------ -- -- --- ----- ----- - ---------- --------- ------ -- --------- - ---------- ---- --- -- -- --- ----------------- --------- ----- -------- -- - -- ----- - ----------------- - ---- - --------------------- - ---展开代码
在这里,我们使用 jwt.sign()
方法生成 JWT。该方法接受一个载荷对象、一个密钥和一个选项对象。选项对象中的 expiresIn
属性指定 JWT 的有效期。
在验证 JWT 时,我们使用 jwt.verify()
方法。该方法接受一个 JWT、一个密钥和一个回调函数。如果 JWT 有效,则回调函数将传递解码的载荷对象。
要在 Express.js 中使用 JWT 进行令牌身份验证,您需要创建一个中间件函数。该函数将从请求头中提取 JWT,并验证其签名和有效性。如果 JWT 有效,则将用户对象添加到请求对象中。
-- -------------------- ---- ------- -- --- ------- ----- ----------------- - ----- ---- ----- -- - ----- ---------- - -------------------------- -- ------------ - ----- ----- - ------------------ ------ ----------------- --------- ----- -------- -- - -- ----- - ------ -------------------- - -------- - - --------- ---------------- -- ------- --- - ---- - -------------------- - -- -- ------ ------------------- ------------------ ----- ---- -- - --------------------- - ----- -------- --- ---展开代码
在这里,我们创建了一个名为 jwtAuthMiddleware
的中间件函数。该函数从请求头中提取 JWT,并使用 jwt.verify()
方法验证其签名和有效性。如果 JWT 有效,则将用户对象添加到请求对象中,并将请求传递给下一个处理程序。否则,将返回 401 或 403 错误。
示例代码
以下是完整的示例代码:
-- -------------------- ---- ------- ----- ------- - ------------------- ----- -------- - -------------------- ----- ------------- - ----------------------------------- ----- ------ - ------------------ ----- --- - ------------------------ ----- --- - ---------- -- ----- ----- -------- - -------------------- -------------------------------------------- - ---------------- ----- ------------------- ---- --- -- ---- ----- ---- - ---------------------- - --------- ------- --------- ------ --- -- ----------- -- ---------------- -------------- ----- ------------------ --------- ----- - ----- ---- - ----- -------------- -------- --- -- ------- - ------ ---------- ------- - ----- ------------- - ----- ------------------------ --------------- -- ---------------- - ------ ---------- ------- - ------ ---------- ------ - --- ------------------------------------- ----- - ---------- --------- --- ------------------------------ ------------ ----- - ----- ---- - ----- ------------------ ---------- ------ --- ------------------------------------ ------- --------- ----- ------- ------ ------------------ ----- ---- ------------------------------- ---------------------------- -- ---- -------------------- ----- ---- -- - ----------------------- --- -- ---- ----------------- ----- ---- -- - -------------------- --- -- ---- --------------------- ----- ----- ---- -- - ----- - --------- -------- - - --------- ----- -------------- - ----- --------------------- ---- ----- ---- - --- ------ --------- --------- -------------- --- ----- ------------ --------------- ----- -- - -- ----- - ------ ---------- - ------------------ --- --- -- ---- ------------------ ------------------------------ - ---------------- ---- ---------------- -------- ---- -- ------ ----- ----------------- - ----- ---- ----- -- - ----- ---------- - -------------------------- -- ------------ - ----- ----- - ------------------ ------ ----------------- --------- ----- -------- -- - -- ----- - ------ -------------------- - -------- - - --------- ---------------- -- ------- --- - ---- - -------------------- - -- ------------------- ------------------ ----- ---- -- - --------------------- - ----- -------- --- --- -- ----- ---------------- -- -- - ---------------------- ---展开代码
在这里,我们使用 Express.js、Passport.js、bcrypt 和 JSON Web Tokens 来构建身份验证系统。我们实现了注册和登录功能,并保护了受保护的路由。我们还使用 JWT 来进行令牌身份验证。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67cbe60ce46428fe9e5051fd