Node.js 如何和Passport实现ACL
Node.js: 是一个异步事件驱动的JavaScript运行时环境,设计用于构建可扩展的网络应用程序。
Passportjs: 是Node.js的身份验证中间件。非常灵活和模块化,可以轻松地集成到任何基于Express的Web应用程序中。它提供了一套全面的策略,支持使用用户名和密码、Facebook、Twitter等进行身份验证。开发人员广泛使用它来创建安全且可扩展的Web应用程序。
使用Node.js实现Passport的ACL步骤:
步骤1: 在任何IDE中创建一个带有项目名称的文件夹(我使用的是VS Code)。请查看下面的文件夹结构。
步骤1: 打开终端并输入“npm init”。按下回车键使用默认值,因为此命令用于设置新的npm包。安装成功后,它将创建一个package.json文件夹。
步骤2: 按下“npm i express ejs”以安装node依赖项。
步骤3: 按下“npm i –save-dev nodemon dotenv”以安装开发环境依赖项。Nodemon允许在任何更改时自动重启服务器,dotenv允许我们使用.env文件存储环境变量,并加载到服务器。
步骤4: 根据以下目录结构制作“.env”和“.gitignore”文件。

.gitignore包含了那些我们不想提交到Git仓库的文件。在这里,我们存储了.env和node_modules,因为它们只包含依赖项,且.env可能包含我们不想与世界共享的敏感信息。

步骤5: 我们最后需要做的是设置package.json,以便我们可以启动服务器。按照以下方式编辑脚本部分:

步骤6: 现在,在终端中按下“npm run devStart”将启动服务器。您应该在终端中得到类似这样的输出。

2: 在 server.js 中使用以下代码设置我们的基本 express 应用程序。
// STEP 1: Install all the necessary dependencies
// add the dependencies with the help of require
const express = require('express')
const app = express()
// To run our app on port 3000
app.listen(3000)
但是,如果我们在编写这段代码后运行我们的服务器,我们将在localhost:300上获得以下页面。

它显示了“无法GET /”,因为我们尚未为应用程序设置任何路由。让我们在第3步中解决这个问题。
3: 在server.js中添加上述代码,并创建一个名为views的文件夹,其中包含index.ejs文件。

4:使用“npm i bcrypt”安装另一个包: bcrypt将允许我们对密码进行哈希处理,并比较哈希后的密码,确保我们的应用程序完全安全。
server.js
// Requiring all the necessary dependencies
const express = require('express')
const app = express()
const bcrpyt = require('bcrypt')
const users = []
// In order to use ejs set up view-engine
app.set('view-engine', 'ejs')
app.use(express.urlencoded({ extended: false }))
// Setting up home-page route
app.get('/', (req, res) => {
res.render('index.ejs', { name: 'Janhvi' })
})
// Set up login page route
app.get('/login', (req, res) => {
res.render('login.ejs')
})
// Set up register page route
app.get('/register', (req, res) => {
res.render('register.ejs')
})
app.post('/register', async (req, res) => {
// Using try catch block in order to
// resolve errors
try {
// Hashing password with bcrypt
const hashedPassword =
await bcrpyt.hash(req.body.password, 10)
users.push({
id: Date.now().toString(),
name: req.body.name,
email: req.body.email,
password: hashedPassword
})
res.redirect('/login')
} catch {
res.redirect('/register')
}
console.log(users)
})
// To run our app on port 3000
app.listen(3000)
login.ejs
<!-- login page -->
<h1>Login</h1>
<!-- Make a simple login form with name, email
and password fields make a submit button
at end -->
<form action="/login" method="POST">
<div>
<label for="name">Name</label>
<input type="text" id="name"
name="name" required>
</div>
<div>
<label for="email">Email</label>
<input type="email" id="email"
name="email" required>
</div>
<div>
<label for="password">Password</label>
<input type="password"
id="password" name="password" required>
</div>
<button type="submit">Login</button>
</form>
<a href="/register">Register</a>
register.ejs
<!-- Register page -->
<h1>Register</h1>
<!-- Make a simple register form with
name, email and password fields
make a submit button at end -->
<form action="/register" method="POST">
<div>
<label for="name">Name</label>
<input type="text" id="name"
name="name" required>
</div>
<div>
<label for="email">Email</label>
<input type="email" id="email"
name="email" required>
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password"
name="password" required>
</div>
<button type="submit">Register</button>
</form>
<a href="/login">Login</a>
在http://localhost:3000/login上期望的输出

http://localhost:3000/register

在输入后,控制台的密码将显示为哈希值

5:使用“npm i passport passport-local express-session express-flash”安装passportjs。
在文件“passport-config.js”中存储所有与Passport相关的信息。现在让我们来看一下具有所需逻辑的所有代码的最终版本。
server.js
// The below code is only suitable for
// development not suitable for production
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config()
}
// Requiring all the necessary dependencies
const express = require('express')
const app = express()
const bcrypt = require('bcrypt')
const passport = require('passport')
const flash = require('express-flash')
const session = require('express-session')
const methodOverride = require('method-override')
const initializePassport = require('./passport-config')
initializePassport(
passport,
email => users.find(user => user.email === email),
id => users.find(user => user.id === id)
)
const users = []
// Setting up the view-engine in order
// to use ejs in code further
app.set('view-engine', 'ejs')
app.use(express.urlencoded({ extended: false }))
app.use(flash())
app.use(session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false
}))
app.use(passport.initialize())
app.use(passport.session())
app.use(methodOverride('_method'))
// Setting up route logic for home page
app.get('/', checkAuthenticated, (req, res) => {
res.render('index.ejs', { name: req.user.name })
})
// Setting up route logic for login page
app.get('/login', checkNotAuthenticated, (req, res) => {
res.render('login.ejs')
})
app.post('/login', checkNotAuthenticated,
passport.authenticate('local', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash: true
}))
app.get('/register', checkNotAuthenticated,
(req, res) => {
res.render('register.ejs')
})
// Hashinhg the passwords for each user
// using bcrypt
app.post('/register', checkNotAuthenticated,
async (req, res) => {
try {
const hashedPassword =
await bcrypt.hash(req.body.password, 10)
users.push({
id: Date.now().toString(),
name: req.body.name,
email: req.body.email,
password: hashedPassword
})
res.redirect('/login')
} catch {
res.redirect('/register')
}
})
// To to login page upon pressing the
// logout button
app.delete('/logout', (req, res) => {
req.logOut()
res.redirect('/login')
})
// If user is authenticated redirect to
// next page otherwise redirect to login
// page
function checkAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return next()
}
res.redirect('/login')
}
function checkNotAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
return res.redirect('/')
}
next()
}
// To run our app on port 3000
app.listen(3000)
passport-config.js
// Requiring all the necessary dependencies
const LocalStrategy = require('passport-local').Strategy
const bcrypt = require('bcrypt')
// Add all the code related to passportjs to
// the main initialize function
function initialize(passport, getUserByEmail, getUserById) {
const authenticateUser = async (email, password, done) => {
const user = getUserByEmail(email)
// If user is null return output
// "no user with that email"
if (user == null) {
return done(null, false,
{ message: 'No user with that email' })
}
// try-catch block to check for correct password
try {
if (await bcrypt.compare(password, user.password)) {
return done(null, user)
} else {
return done(null, false,
{ message: 'Password incorrect' })
}
} catch (e) {
return done(e)
}
}
passport.use(new LocalStrategy(
{ usernameField: 'email' }, authenticateUser))
passport.serializeUser((user, done) => done(null, user.id))
passport.deserializeUser((id, done) => {
return done(null, getUserById(id))
})
}
// Exporting the initialize function
module.exports = initialize
index.ejs
<!-- Index page which will display
the Hi user_name -->
<h1>Hi <%= name %></h1>
<!-- Setting up a logout button in
order to exit the page -->
<form action="/logout?_method=DELETE" method="POST">
<button type="submit">Log Out</button>
</form>
login.ejs
<!-- login page -->
<h1>Login</h1>
<!-- Adding embedded javascript code to
check for errors -->
<% if (messages.error) { %>
<%= messages.error %>
<% } %>
<!-- Make a simple login form with
name, email and password fields
make a submit button at the end -->
<form action="/login" method="POST">
<div>
<label for="email">Email</label>
<input type="email" id="email"
name="email" required>
</div>
<div>
<label for="password">Password</label>
<input type="password"
id="password" name="password" required>
</div>
<button type="submit">Login</button>
</form>
<a href="/register">Register</a>
register.ejs
<!-- Register page -->
<h1>Register</h1>
<!-- Make a simple register form with
name, email and password fields
make a submit button at the end -->
<form action="/register" method="POST">
<div>
<label for="name">Name</label>
<input type="text" id="name"
name="name" required>
</div>
<div>
<label for="email">Email</label>
<input type="email" id="email"
name="email" required>
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password"
name="password" required>
</div>
<button type="submit">Register</button>
</form>
<a href="/login">Login</a>
6:使用“npm i method-override”安装另一个包- 其余的代码保持不变。
启动服务器后将出现的第一个页面是登录页面。

如果您已经注册过,请使用相同的电子邮件和密码登录。

如果您尚未注册并且尝试登录,则将获得以下结果。

首先注册自己,记住邮箱和密码,然后再试着登录。

成功注册和登录后,您将在您的页面上看到以下内容:“欢迎来到GeeksforGeeks your_name”。

输出:

极客教程