node.js+captchapng+jsonwebtoken实现登录验证示例

下面是详细的 "node.js+captchapng+jsonwebtoken实现登录验证示例" 的攻略:

一、背景

在网站开发中,登录是非常普遍的需求。而如何确保用户登录的安全性,是需要我们考虑的重要问题之一。本文将介绍如何使用 node.js、captchapng 和 jsonwebtoken 模块,实现基于验证码和 token 的登录验证。

二、前置知识

在继续阅读本文之前,需要你掌握以下知识:

  • node.js 环境的搭建和基础语法的学习;
  • HTTP 请求和响应的基本概念;
  • Express 框架的使用方法;
  • 安装和使用 captchapng 和 jsonwebtoken 模块。

三、具体实现

1. 实现验证码

为了防止机器人暴力破解密码,我们需要在登录界面加入验证码。captchapng 模块可以帮助我们生成验证码图片。

首先,我们需要安装 captchapng 模块:

npm install captchapng

然后,在路由中添加生成验证码图片的代码:

const captchapng = require('captchapng');
const express = require('express');
const router = express.Router();

router.get('/captcha', (req, res) => {
  const width = 80;
  const height = 30;
  const code = parseInt(Math.random() * 9000 + 1000);
  const p = new captchapng(width, height, code);
  p.color(0, 0, 0, 0); // 背景颜色
  p.color(80, 80, 80, 255); // 文字颜色

  const img = p.getBase64();
  const imgbase64 = Buffer.from(img, 'base64');

  res.writeHead(200, {
    'Content-Type': 'image/png'
  });
  res.end(imgbase64);
});

以上代码中,我们定义了 /captcha 路由,用于生成验证码。代码中,我们首先定义了验证码的宽度和高度、验证码的内容(四位数字);然后,使用 captchapng 模块生成 png 格式的图片,并设置了背景颜色和文字颜色;最后,将生成的图片以 base64 格式返回到浏览器端。

2. 实现登录验证

接下来,我们需要使用 jsonwebtoken 模块来实现登录验证。Jsonwebtoken 是一个令牌(token)生成器和解析器,可以帮助我们生成并验证令牌。

先安装 jsonwebtoken 模块:

npm install jsonwebtoken

接着,在路由中添加验证用户名、密码和验证码的代码:

const jwt = require('jsonwebtoken');
const express = require('express');
const router = express.Router();

router.post('/login', async (req, res) => {
  const { username, password, captcha } = req.body;
  if (captcha !== req.session.captcha) {
    res.status(400).json({ success: false, message: '验证码错误' });
    return;
  }

  // 根据实际情况,需要从数据库或其它数据源中获取用户信息
  const valid = username === 'admin' && password === '123456';
  if (!valid) {
    res.status(400).json({ success: false, message: '用户名或密码错误' });
    return;
  }

  const token = jwt.sign({ username }, 'secret', { expiresIn: '1h' });
  res.json({ success: true, token });
});

以上代码中,我们定义了 /login 路由,用于验证用户名、密码和验证码,并返回生成的 token。

在代码中,我们首先判断验证码是否正确,如果不正确,则返回错误提示;然后,根据实际情况,从数据库或其它数据源中获取用户信息,判断用户名和密码是否正确,如果不正确,则返回错误提示;最后,使用 jsonwebtoken 模块生成 token,并返回给浏览器端。

3. 实现 token 鉴权

登录验证完成后,我们需要在接下来的业务逻辑中,使用 token 进行鉴权。

const jwt = require('jsonwebtoken');
const express = require('express');
const router = express.Router();

router.get('/info', async (req, res) => {
  try {
    const token = req.headers.authorization.split(' ')[1];
    const decoded = jwt.verify(token, 'secret');
    const { username } = decoded;

    // 根据实际情况,需要从数据库或其它数据源中获取用户信息
    const user = { username, role: 'admin' };
    res.json({ success: true, user });
  } catch (e) {
    res.status(401).json({ success: false, message: 'Token 鉴权失败' });
  }
});

以上代码中,我们定义了 /info 路由,用于获取登录用户的信息。在代码中,我们首先从请求头中获取 token,然后使用 jsonwebtoken 模块对 token 进行鉴权,如果鉴权成功,则返回用户信息;否则,返回错误提示。

四、示例说明

为了更好地理解以上实现过程,我们将给出两个示例说明。

示例一:前后端分离应用

在前后端分离的应用中,前端和后端是分开部署的。前端发送请求到后端,后端返回 JSON 格式的数据,前端再进行处理和渲染。

以下是一个使用 Vue.js 和 Express 实现的前后端分离应用的示例:

前端首页代码:

<template>
  <div>
    <h1>我的网站</h1>
    <p v-if="!loginUser">请登录</p>
    <p v-if="loginUser">欢迎 {{ loginUser.username }}</p>
    <button v-if="!loginUser" @click="showLoginDialog = true">登录</button>
    <button v-if="loginUser" @click="logout">退出</button>
    <div v-if="showLoginDialog">
      <input type="text" v-model="username" placeholder="请输入用户名"/>
      <input type="password" v-model="password" placeholder="请输入密码"/>
      <input type="text" v-model="captcha" placeholder="请输入验证码"/>
      <img :src="'/api/captcha?' + Math.random()" @click="refreshCaptcha" />
      <button @click="login">登录</button>
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        loginUser: null,
        showLoginDialog: false,
        username: '',
        password: '',
        captcha: ''
      }
    },
    methods: {
      refreshCaptcha() {
        this.$refs.captchaImg.src = '/api/captcha?' + Math.random();
      },
      async login() {
        const { data } = await axios.post('/api/login', {
          username: this.username,
          password: this.password,
          captcha: this.captcha
        });
        if (data.success) {
          // 登录成功,将 token 存储到 localStorage 中
          localStorage.setItem('token', data.token);
          this.showLoginDialog = false;
          this.fetchUserInfo();
        } else {
          alert(data.message)
        }
      },
      async logout() {
        localStorage.removeItem('token');
        this.loginUser = null;
      },
      async fetchUserInfo() {
        const token = localStorage.getItem('token');
        if (token) {
          try {
            const { data } = await axios.get('/api/info', {
              headers: { Authorization: 'Bearer ' + token }
            });
            this.loginUser = data.success ? data.user : null;
          } catch (e) {
            console.error(e);
          }
        }
      }
    },
    mounted() {
      this.fetchUserInfo();
    }
}
</script>

后端代码:

const express = require('express');
const jwt = require('jsonwebtoken');

const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'));

app.get('/api/captcha', (req, res) => {
  // 生成验证码图片
});

app.post('/api/login', (req, res) => {
  const { username, password, captcha }= req.body;
  // 验证用户名、密码和验证码
  // 生成 token 并返回
});

app.get('/api/info', (req, res) => {
  const { authorization } = req.headers;
  const token = authorization.split(' ')[1];
  // 鉴权 token,返回用户信息
});

app.listen(3000, () => {
  console.log('Server started on http://localhost:3000');
});

在以上示例中,我们定义了一个前端首页,在首页中实现了登录和注销功能。当用户登录成功后,将 token 存储到浏览器的 localStorage 中;在获取用户信息时,需要将存储在 localStorage 中的 token 从请求头中传递给服务器端。

示例二:基于 session 的应用

session 是另外一种实现用户登录验证的方式。以下是一个基于 session 实现的应用的示例。

前端代码:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>我的网站</title>
</head>
<body>
  <h1>我的网站</h1>

  <div>
    <p v-if="!loginUser">请登录</p>
    <p v-if="loginUser">欢迎 {{ loginUser.username }}</p>
    <button v-if="!loginUser" @click="showLoginDialog = true">登录</button>
    <button v-if="loginUser" @click="logout">退出</button>
    <div v-if="showLoginDialog">
      <input type="text" v-model="username" placeholder="请输入用户名"/>
      <input type="password" v-model="password" placeholder="请输入密码"/>
      <input type="text" v-model="captcha" placeholder="请输入验证码"/>
      <img :src="'/captcha?' + Math.random()" @click="refreshCaptcha" />
      <button @click="login">登录</button>
    </div>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script>
    new Vue({
      el: 'body',
      data: {
        loginUser: null,
        showLoginDialog: false,
        username: '',
        password: '',
        captcha: ''
      },
      methods: {
        refreshCaptcha() {
          this.$refs.captchaImg.src = '/captcha?' + Math.random();
        },
        async login() {
          const { data } = await axios.post('/login', {
            username: this.username,
            password: this.password,
            captcha: this.captcha
          });
          if (data.success) {
            // 登录成功,显示欢迎信息和注销按钮
            this.showLoginDialog = false;
            this.fetchUserInfo();
          } else {
            alert(data.message)
          }
        },
        async logout() {
          await axios.post('/logout');
          this.loginUser = null;
        },
        async fetchUserInfo() {
          const { data } = await axios.get('/user');
          if (data.success) {
            this.loginUser = data.user;
          }
        }
      },
      async mounted() {
        this.fetchUserInfo();
      }
    })
  </script>
</body>
</html>

后端代码:

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

const app = express();

app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  cookie: { secure: false }
}));

app.get('/captcha', (req, res) => {
  // 生成验证码图片
});

app.post('/login', (req, res) => {
  const { username, password, captcha }= req.body;
  // 验证用户名、密码和验证码
  // 将用户信息存入 session 中
});

app.get('/user', (req, res) => {
  const { user } = req.session;
  if (!user) {
    res.json({ success: false, message: '请先登录' });
  } else {
    res.json({ success: true, user });
  }
});

app.post('/logout', (req, res) => {
  // 销毁 session
});

app.listen(3000, () => {
  console.log('Server started on http://localhost:3000');
});

在以上示例中,我们利用了 Express 的 session 中间件,来存储用户信息。具体地,当用户登录成功时,我们将用户信息存入 session 中;当获取用户信息时,我们从 session 中读取用户信息。当用户注销时,我们销毁 session。

五、结语

本文详细讲解了如何使用 node.js、captchapng 和 jsonwebtoken 模块,实现基于验证码和 token 的登录验证。示例代码同时也给出了如何在前后端分离应用和基于 session 的应用中,实现登录验证的方法。希望这篇文章能够对您有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:node.js+captchapng+jsonwebtoken实现登录验证示例 - Python技术站

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

相关文章

  • node.js编译生成错误提示fatal error LNK1112/1123的解决方法

    Node.js编译生成错误提示fatal error LNK1112/1123的解决方法 什么是LNK1112/1123错误 在使用Node.js编译时,有时会遇到以下错误提示: LINK: fatal error LNK1112: module machine type ‘x64’ conflicts with target machine type ‘X…

    node js 2023年6月8日
    00
  • es6和commonJs的区别解析

    ES6和CommonJS的区别解析 ES6和CommonJS是Javascript中两种不同的模块系统,都能够让开发人员更好地组织代码和管理依赖关系,但它们在许多方面都有所不同。 ES6模块系统 ES6模块系统定义了一种新的语法形式,可以让开发人员更好地编写面向对象的代码,并支持静态分析、编译时优化、自动代码拆分等高级特性。 创建ES6模块非常简单,只需要在…

    node js 2023年6月8日
    00
  • JS在IE下缺少标识符的错误

    JS在IE下缺少标识符错误通常是由于代码中缺少分号导致的。这个错误在其他浏览器中可能不会出现,但在IE浏览器中会非常常见。下面是了解该错误以及如何解决该错误的完整攻略: 1.了解“JS在IE下缺少标识符的错误”是什么 当在IE浏览器中使用某些JavaScript代码时,可能会看到以下错误消息:缺少标识符。这是因为IE在JavaScript代码中有一个分号缺失…

    node js 2023年6月8日
    00
  • nodejs 日志模块winston的使用方法

    下面是关于“nodejs 日志模块winston的使用方法”的完整攻略: 什么是winston winston 是一个流行的 Node.js 日志记录库。它允许开发人员在应用程序中方便地配置、记录和存储日志消息,而无需编写适用于多个日志级别的自定义代码。winston 支持多种目标,例如文件、数据库、控制台和 syslog。 安装winston 在Node.…

    node js 2023年6月8日
    00
  • 关于node+mysql数据库连接池连接

    我来为你讲解一下关于node.js和mysql数据库连接池连接的完整攻略。 1. 安装 mysql 模块 我们需要先安装mysql模块来连接mysql数据库,输入以下命令来安装: npm install mysql 2. 创建连接池 接下来,我们需要创建数据库连接池,并配置连接数据库的信息,如下所示: const mysql = require(‘mysql…

    node js 2023年6月8日
    00
  • 浅析Nodejs npm常用命令

    我将为您详细讲解“浅析Nodejs npm常用命令”的完整攻略。 一、 什么是npm? npm是Node.js的包管理工具,它能够帮助我们安装、管理依赖,以及发布我们自己的包。 二、npm常用命令 1. npm init npm init命令可以让我们创建一个新的package.json文件,这个文件是用来描述我们的项目的,可以在这个文件中设置项目的基本信息…

    node js 2023年6月8日
    00
  • js常用代码段整理

    JS常用代码段整理攻略 在Web开发中,常常需要用到JavaScript来实现动态效果和交互行为。为了提高开发效率和代码质量,我们可以整理出常用的JavaScript代码段,方便在项目中复用。本文将分为以下几个部分来介绍如何整理JS常用代码段: 1. 收集常用代码段 在开发过程中,积累下来的常用代码段十分重要。积累的方式可以是自己写的,也可以是网络上扒得过来…

    node js 2023年6月8日
    00
  • 如何利用nodejs实现命令行游戏

    下面是基于Node.js实现命令行游戏的完整攻略: 1.了解Node.js 首先,你需要了解Node.js是一个什么样的东西。Node.js是一个基于Chrome V8 JavaScript引擎的开源、跨平台的后端JavaScript运行环境,可以用于快速构建高性能、可扩展的网络应用程序。Node.js它提供了一些内置模块,包括文件系统、HTTP等,使得可以…

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