Node.js express中的身份认证的实现

Node.js express中的身份认证是Web应用开发中非常重要的一环。以下是实现身份认证的完整攻略:

Step1:安装相关模块

首先安装以下模块:

  • express-session:用于维持用户的会话状态
  • passport:提供了运用于Node.js的身份验证中间件
  • passport-local:用于基于用户名和密码的身份验证策略
  • bcryptjs:用于加密用户密码

安装命令为:

npm install express-session passport passport-local bcryptjs

Step2:配置中间件

在创建Express应用程序的过程中,需要将以上安装的模块作为中间件使用,并指定相应的配置选项,例如:

const session = require('express-session');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const bcrypt = require('bcryptjs');

// 配置 express 中间件
app.use(session({
    secret: 'secret-key',
    resave: false,
    saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());

// 配置本地身份验证策略
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 (!bcrypt.compareSync(password, user.password)) { return done(null, false, { message: 'Incorrect password.' }); }
            return done(null, user);
        });
    }
));

// 用于序列化和反序列化用户对象
passport.serializeUser(function(user, done) {
    done(null, user.id);
});

passport.deserializeUser(function(id, done) {
    User.findById(id, function(err, user) {
        done(err, user);
    });
});

在这个示例中,我们配置了一个本地身份验证策略,该策略使用了bcrypt.js密码加密算法来对用户密码进行加密,然后与数据库中的加密密码进行比较以验证用户身份。我们还实现了用户对象的序列化和反序列化,以便将用户保存在会话中。

Step3:编写登录和注册路由

在实现中间件后,需要编写登录和注册路由:

// 登录页面
app.get('/login', function(req, res) {
    res.render('login');
});

app.post('/login', passport.authenticate('local', { failureRedirect: '/login' }), function(req, res) {
    res.redirect('/');
});

// 注册页面
app.get('/register', function(req, res) {
    res.render('register');
});

app.post('/register', function(req, res) {
    const { username, password } = req.body;
    const hash = bcrypt.hashSync(password, 10);
    const newUser = new User({ username, password: hash });
    newUser.save(function(err) {
        if (err) {
            console.log(err);
            res.redirect('/register');
        } else {
            res.redirect('/login');
        }
    });
});

在这个示例中,我们为登录和注册分别编写了get和post路由。对于登录路由,我们使用了passport.authenticate中间件来进行身份验证,并指定了验证策略为本地验证策略。对于注册路由,我们使用bcrypt.hashSync函数对用户密码进行加密,并将加密后的密码保存到数据库中。

Step4:编写路由保护中间件

编写路由保护中间件是实现身份认证的一部分,它将确保被保护的路由只有在用户已登录的情况下才能访问。以下是一个示例:

function ensureAuthenticated(req, res, next) {
    if (req.isAuthenticated()) {
        return next();
    } else {
        res.redirect('/login');
    }
}

app.get('/', ensureAuthenticated, function(req, res) {
    res.render('index', { user: req.user });
});

在这个示例中,我们定义了一个中间件函数ensureAuthenticated,该函数将检查用户是否已被验证通过(即已经登录)。如果用户已经登录,它将继续执行下一步,否则将用户重定向到登录页面。

Step5:编写用户注销路由

最后,需要实现用户注销,以便用户能够结束会话并从会话中删除存储的用户对象。以下是一个示例:

app.get('/logout', function(req, res) {
    req.logout();
    res.redirect('/login');
});

在这个示例中,我们使用req.logout()函数来将用户的会话状态设置为未验证,并将用户重定向到登录页。

通过上面的步骤,我们完成了一个基础的身份认证系统。

示例说明:

下面给出两个示例,分别说明了在实现身份认证过程中使用的具体技术和方法。

示例1:使用JWT进行身份认证

在实现身份认证过程中,可以使用JSON Web Token(JWT)来生成和验证身份认证令牌。在这个示例中,我们使用jsonwebtoken模块来实现JWT身份认证。以下是示例代码:

const jwt = require('jsonwebtoken');

// 生成token
app.post('/login', function(req, res) {
    const { username, password } = req.body;
    if (username === 'admin' && password === 'admin') {
        const token = jwt.sign({ username }, 'secret-key');
        res.json({ token });
    } else {
        res.status(401).json({ message: 'Username or password incorrect' });
    }
});

// 验证token
function verifyToken(req, res, next) {
    const bearerHeader = req.headers['authorization'];
    if (typeof bearerHeader !== 'undefined') {
        const bearerToken = bearerHeader.split(' ')[1];
        req.token = bearerToken;
        jwt.verify(req.token, 'secret-key', function(err, decoded) {
            if (!err) {
                req.user = decoded;
                next();
            } else {
                res.sendStatus(403);
            }
        });
    } else {
        res.sendStatus(403);
    }
}

app.post('/protected', verifyToken, function(req, res) {
    res.json({ message: 'Access granted', user: req.user });
});

在这个示例中,我们定义了如下路由:

  • /login:用于生成JWT令牌和验证用户的登录凭证。
  • /protected:需要通过Token验证身份才能访问的加密路由。

/login路由中,我们使用jwt.sign()来生成一个包含用户名的令牌,然后将其作为JSON响应返回给客户端。在/protected路由中,我们使用verifyToken中间件来验证请求中是否包含正确的Token。如果Token是有效的,我们将请求持有的用户名附加到响应中,向用户显示已通过身份验证。

示例2:使用Passport-local-mongoose进行身份认证

Passport-local-mongoose是Passport.js中间件的一个功能强大的扩展,它简化了用户身份认证的代码实现。该库提供了一种轻松的方式在Mongoose模型上构建本地Passport.js身份验证。以下是示例代码:

const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('./models/user');
const mongoose = require('mongoose');
const passportLocalMongoose = require('passport-local-mongoose');

const mongoURI = 'mongodb://localhost:27017/db';
mongoose.connect(mongoURI, { useNewUrlParser: true, useUnifiedTopology: true });

// 在用户模型中使用Passport-local-mongoose插件
User.plugin(passportLocalMongoose, {
    usernameField: 'email'
});

// 配置本地身份验证策略
passport.use(new LocalStrategy({ usernameField: 'email' }, User.authenticate()));

// 用于序列化和反序列化用户对象
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

在这个示例中,我们使用Mongoose来连接MongoDB数据库,并使用了passportLocalMongoose插件。该插件为我们提供了新的模型方法User.authenticate(),它自动在用户和密码字段上进行身份验证。我们还实现了用户对象的序列化和反序列化,类似于上一步中的做法。

通过这个示例,我们可以看出使用Passport-local-mongoose可以大大简化身份认证的代码实现,帮助减轻开发人员的工作负担。

总结:

身份认证是Web应用开发的重要组成部分,我们可以使用第三方模块和插件来实现符合标准的身份验证流程,减轻开发人员的工作量。目前,市场上有大量的身份认证解决方案以及现成的身份认证插件和模块可供选择,在实现身份认证过程中可以根据具体应用场景和需求选择合适的技术方案。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Node.js express中的身份认证的实现 - Python技术站

(0)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • Node的stream数据流你了解吗

    当我们面对大数据时,如何有效地处理数据是一个至关重要的问题。而stream数据流可以帮助我们有效地处理数据。Node.js提供了一个非常强大的模块——stream模块,它可以帮助我们实现流式数据的读写操作,可以极大地提高数据处理的效率,减少内存占用。下面让我们来一起了解一下Node.js的stream数据流。 一、stream的概念 stream(流)是一组…

    node js 2023年6月8日
    00
  • socket.io断线重连的几种场景及处理方法

    Socket.IO断线重连的几种场景及处理方法 在使用Socket.IO时,由于网络或服务器等原因,可能会出现断线的情况。本文将详细讲解Socket.IO断线重连的几种场景及处理方法。 场景一:客户端主动断开连接 当客户端主动断开连接时,Socket.IO会触发disconnect事件。如果需要重连,可以在disconnect事件中调用socket.conn…

    node js 2023年6月8日
    00
  • Node 代理访问的实现

    Node 代理访问的实现可以分为两步: 使用 http.request 或 https.request 创建一个代理请求,并将请求转发给目标服务器。示例如下: const http = require(‘http’); http.createServer(function(req, res) { console.log(req.url); const opt…

    node js 2023年6月8日
    00
  • 关于node编写文件上传的接口的坑及解决

    当使用Node.js编写文件上传的接口时,可能会遇到以下坑点: 对于大文件上传,内存可能会不足,导致服务器崩溃。因此,需要使用流的方式读取上传文件,而不是将整个文件直接读取到内存中。 在多个文件同时上传或者文件较大时,可能会导致上传速度变慢或者上传过程中出现错误。这个坑点可以通过对上传进度进行监控和限制上传速度来解决。 针对这些坑点,下面是详细的解决方案: …

    node js 2023年6月8日
    00
  • node里的filesystem模块文件读写操作详解

    Node.js中文件读写操作详解 在Node.js中,可以使用fs模块进行文件系统相关的操作,如文件读写、目录操作等。 读取文件 使用fs.readFile()方法可以读取文件的内容,该方法的参数为文件路径和回调函数,回调函数的参数包含了错误信息和文件内容。 示例1:读取文本文件 const fs = require(‘fs’); fs.readFile(‘…

    node js 2023年6月8日
    00
  • 解决Node.js使用MySQL出现connect ECONNREFUSED 127.0.0.1:3306的问题

    当我们使用Node.js连接MySQL数据库时,有可能会出现connect ECONNREFUSED 127.0.0.1:3306的错误。这种错误通常是由于MySQL服务未启动、端口被占用、权限问题等原因引起的。接下来我将详细介绍如何解决这个问题。 问题分析 当我们使用Node.js连接MySQL数据库时,通常使用第三方库,如mysql、mysql2等。这些…

    node js 2023年6月8日
    00
  • Nodejs读取文件时相对路径的正确写法(使用fs模块)

    当在Node.js应用程序中读取文件时,最常见的错误是文件路径错误。路径的总是以根目录的相对比较位置。在本文中,我们将讨论如何在使用fs模块时,正确设置文件路径并确保读取文件。 正确的相对路径表示法 使用相对路径时,始终记住相对于执行Node.js应用程序的文件所在的目录。 同时相对路径可以使用 ./ 或者 __dirname 辅助完成。 __dirname…

    node js 2023年6月8日
    00
  • 实战node静态文件服务器的示例代码

    下面是关于实战node静态文件服务器的示例代码的完整攻略: 1. 安装Node 首先,在本地安装最新版本的Node.js,官网下载地址为 https://nodejs.org/zh-cn/download/ 。 2. 创建项目目录 在本地创建一个新的项目目录,例如: mkdir my-node-server 3. 初始化项目 在项目目录下使用以下命令初始化一…

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部