如何通过数据验证防止 Web API 攻击 - Web API 安全指南

充分的数据保护和用户保密是网页开发者的主要责任。因此,在构建 API 终端时,确保最高可能的安全性至关重要。

应用程序安全是客户端和服务器开发者共同的责任,一方的疏忽可能会造成灾难性后果。统计数据显示,2023 年的数据泄露导致全球超过 800 万个数据记录暴露。

在本文中,我将重点介绍 API 安全的关键领域,其中包括数据验证。这个概念对帮助您保护 API 免受通过恶意用户数据进行的网络攻击非常重要。这个教程非常适合所有后端开发者,无论经验多少。

为了能够跟随本教程,这里有一些先决条件:

  • Node.js 知识
  • npm 和包安装知识

有了这些准备,让我们开始吧。

(本文内容参考:java567.com)

数据验证是如何工作的?

首先,什么是数据验证?数据验证简单来说就是确保来自外部来源的数据在进行进一步数据处理之前的准确性和可靠性。

这是 Web API 安全的关键组成部分,因为它对于防止网络注入攻击、SQL 攻击和 NoSQL 攻击至关重要。要了解更多信息,您可以查看此链接。

请注意,数据验证不仅仅需要在以下后端操作中进行:

  • 用户登录和注册
  • 响应查询
  • 更新服务器数据库

所有这些都可能被恶意黑客利用,以获取对服务器数据库的访问权限,并获取敏感用户详细信息,甚至通过格式化整个数据库来制造混乱。

流行的数据验证工具

到目前为止,有很多工具可以帮助程序员在 API 开发中实现高效的数据验证。

它们帮助您避免重新发明验证数据的长正则表达式代码的轮子。它们提供了大量功能,包括错误处理和验证定制功能。

其中一些工具包括:

  • Joi
  • Zod
  • Yup
  • AJv
  • Valibot
  • Validator.js
  • Superstruct

为了进一步阐明这些工具,我们将比较上述最受欢迎的数据验证工具中的一些。

数据验证工具的优缺点

为了进一步让您了解这些 JavaScript 验证工具,我将重点介绍其中三种流行的 JavaScript 验证工具的一些优缺点。

Joi

优点
  • 拥有强大的、庞大的用户社区和开发支持
  • 具有处理复杂验证的内置功能
缺点
  • 其语法相当冗长

Zod

优点
  • 与 TypeScript 项目轻松兼容
  • 具有高效的错误处理能力
缺点
  • 不支持异步验证。

Yup

优点
  • 主要使用声明性语法设置其验证工具,从而赋予其简单性
  • 具有可比较的快速性能。
缺点
  • 不提供自定义功能
  • 其处理复杂验证的能力有限

为了本教程的目的,我们将使用 Joi 作为我们的数据验证工具。

简介 Joi

Joi 是一个简单高效的基于 JavaScript 的数据验证工具,它基于模式类型配置。

它具有用于验证各种形式数据出现的内置功能,但不限于布尔值、字符串、函数和区间。它还可以处理复杂的验证操作。

此外,它提供了最小化的缓存功能。有关该工具的更多信息可以在此处找到。

如何设置 Joi

在本节中,我们将在本地环境中设置 Joi。要安装 Joi,请通过命令行导航到代码文件夹,并运行以下命令:

npm i joi

应该显示安装成功的消息。完成后,我们可以演示在我们的演示 API 中使用 Joi 验证用户注册的强大功能。

演示项目

在这个项目中,您将使用 Joi 来验证从客户端接收到的用于在服务器上注册的输入。可以在这里找到用于 Node.js 应用程序的用户注册功能的默认代码。

继续将已安装的 Joi 包导入到您的代码中:

const Joi = require("joi");

在编写我们的注册控制器之前,我们将在代码文件中初始化 Joi 库:

const SignUpSchema = Joi.object({});

在这个项目中,我们将验证从客户端接收到的 email、password 和 username 参数。

const SignUpSchema = Joi.object({
    email: Joi.string().email({
        minDomainSegments: 2,
        tlds: {
            allow: ['com', 'net']
        }
    }),
    username: Joi.string().alphanum().min(3).max(15).required(),
    password: Joi.string().min(8).required()
});

email 参数对象确保电子邮件地址是一个字符串,并且域站点限制为 .com 和 .net,不允许其他形式的域。

对于 username 参数,它确保它是一个包含字母和数字的字符串,最小字符数为 3,最大字符数为 15。required 函数确保必须满足这些条件,否则整个请求将无法通过验证。

password 参数确保提供的密码是以字符串格式提供的,最小字符数为 8,并且也是必需的。

要将其应用到我们的端点中,我们将其包含在控制器函数中:

const { error, value } = SignUpSchema.validate(req.body, { abortEarly: false });
if (error) {
    res.status(400).json(error.details);
    return;
}

此函数在将用户详细信息插入数据库之前执行。模式尝试验证接收到的输入,然后如果成功验证,继续到数据库。

abortEarly 功能包括以允许评估所有参数。如果有任何错误,所有错误都将显示出来。

以上内容也可以在登录控制器函数中复制。您还可以查看 Joi 使用其他复杂验证选项的文档。

项目的最终代码如下所示:

const jwt = require("jsonwebtoken");
const userSchema = require("../Schema/User");
const Joi = require("joi");
const bcrypt = require("bcrypt");
const { createNewColumn, checkRecordsExists, insertRecord } = require('../utils/sqlSchemaFunction');

const generateAccessToken = (use) => {
    return jwt.sign({ userID: use }, process.env.JWT, { expiresIn: "1d" });
}

const SignUpSchema = Joi.object({
    email: Joi.string().email({ minDomainSegments: 2, tlds: { allow: ['com', 'net'] } }),
    username: Joi.string().alphanum().min(3).max(15).required(),
    password: Joi.string().min(8).required()
});

const loginSchema = Joi.object({
    email: Joi.string().email({ minDomainSegments: 2, tlds: { allow: ['com', 'net'] } }),
    password: Joi.string().min(8).required()
});

const register = async (req, res) => {
    const email = req.body.email;
    const password = req.body.password;

    if (!email || !password) {
        res.status(400).json("Please supply the email or password");
        return; 
    }

    const { error, value } = SignUpSchema.validate(req.body, { abortEarly: false });
    if (error) {
        res.status(400).json(error.details);
        return;
    }

    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(password, salt);
    const user = {
        username: req.body.username,
        email: email,
        password: hashedPassword
    };

    try {
        const userAlreadyExists = await checkRecordsExists("users", "email", email);
        if (userAlreadyExists) {
            res.status(400).json("Email must be unique");
        } else {
            await insertRecord("users", user);
            res.status(200).json("User created successfully");
        }
    } catch (err) {
        res.status(500).json({ err: err.message });
    }
};

module.exports = { register };

在这里插入图片描述

在 Postman 中进行 API 测试

确保代码遵循我们定义的模式,结果是成功执行的。

结论

至此,教程已经结束。希望您已经了解了数据验证、各种数据验证工具以及数据验证最佳实践。

(本文内容参考:java567.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/531614.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

windows安装Redis,Mongo,ES并快速基本掌握开发流程

前言 这里只是一些安装后的基础操作,后期会学习更加深入的操作 基础操作 前言RedisRedis启动idea集成Redisjedis技术 Mongodbwindows版Mongodb的安装idea整合Mongodb ES(Elasticsearch)ESwindows下载ES文档操作idea整合ES低级别ES整合高级别ES整合 Redis Redis是…

HarmonyOS 开发-Grid和List内拖拽交换子组件位置

介绍 本示例分别通过onItemDrop()和onDrop()回调,实现子组件在Grid和List中的子组件位置交换。 效果图预览 使用说明: 拖拽Grid中子组件,到目标Grid子组件位置,进行两者位置互换。拖拽List中子组件,到目标List子组件…

【进阶六】Python实现SDVRPTW常见求解算法——自适应大邻域算法(ALNS)

基于python语言,采用经典自适应大邻域算法(ALNS)对 带硬时间窗的需求拆分车辆路径规划问题(SDVRPTW) 进行求解。 目录 往期优质资源1. 适用场景2. 代码调整2.1 需求拆分2.2 需求拆分后的服务时长取值问题 3. 求解结果4…

CADMap3D2024 2023下载地址及安装教程

CAD Map 3D是由Autodesk开发的一款专业的地图制作和GIS(地理信息系统)软件。它是AutoCAD系列软件的一个扩展,提供了一系列特定于地理数据的工具和功能。 CAD Map 3D主要用于处理和管理与地理空间相关的数据,在地图制作、城市规划…

洗地机哪个品牌质量好?四大高口碑优质款式直入

如今,保持家居地面清洁整洁已成为生活中的重要任务。在这方面,洗地机作为一种高效的清洁工具备受青睐。然而,市场上的洗地机种类繁多,选择起来常常让人头疼。所以,哪个品牌的洗地机质量更好呢?以下是几款备…

Java 继承

1 继承 1.1 为什么需要继承 Java中使用类对现实世界中实体来进行描述,类经过实例化之后的产物对象,则可以用来表示现实中的实体,但是 现实世界错综复杂,事物之间可能会存在一些关联,那在设计程序是就需要考虑 比如&…

论文笔记:面向实体的多模态对齐与融合网络假新闻检测

整理了2022TMM期刊 Entity-Oriented Multi-Modal Alignment and Fusion Network for Fake News Detection)论文的阅读笔记 背景模型改进的动态路由算法Cross-Modal Fusion 实验 背景 现有的假新闻方法对多模态特征进行各种跨模态交互和融合,在检测常见假…

刷题之Leetcode203题(超级详细)

203.移除链表元素 力扣题目链接(opens new window)https://leetcode.cn/problems/remove-linked-list-elements/ 题意:删除链表中等于给定值 val 的所有节点。 示例 1: 输入:head [1,2,6,3,4,5,6], val 6 输出:[1,2,3,4,5] …

C++ stl容器vector的认识与简单使用

目录 前言: 本篇文档图片引用自:https://cplusplus.com/reference/vector/vector/ 1.vector的结构 2.迭代器类型 3.构造函数 4.迭代器 反向迭代器遍历 const迭代器 5.容量 maxsize shrink_to_fit reverse resize 6.修改 insert和erase 7.…

心跳机制原理学习

心跳机制 应用场景: 在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙…

4月6号排序算法(2)

堆排序 讲堆排序之前我们需要了解几个定义 什么叫做最大堆,父亲节点,以及孩子节点 将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。 每个节点都是它的子树的根节点的父亲 。 反过来每个节点都是它父亲的孩子 。 …

Matplotlib实现数据可视化

Matplotlib是Python中应用较为广泛的绘图工具之一,首次发布于2007年。它在函数设计上参考了MATLAB,因此名字以"Mat"开头,中间的"plot"代表绘图功能,结尾的"lib"表示它是一个集合。Matplotlib支持众…

HarmonyOS实战开发-短时任务

介绍 本示例主要展示后台任务中的短时任务。 通过ohos.resourceschedule.backgroundTaskManager ,ohos.app.ability.quickFixManager 等接口实现应用热更新的方式去展现短时任务机制。 效果预览 使用说明 1.安装本应用之前,先编译好未签名的应用包&a…

【MPI并行程序】完美解决Attempting to use an MPI routine before initializing MPI

文章目录 错误原因解决方案 最近在写并行程序,犯了一个小错误,记录一下,以防止以后再犯。 Attempting to use an MPI routine before initializing MPI(在初始化 MPI 之前尝试使用 MPI 例程) 错误原因 这个错误通常是因…

MySQL学习笔记2——基础操作

基础操作 一、增删改查1、添加数据2、删除数据3、修改数据4、查询语句 二、主键三、外键和连接1、外键2、连接 一、增删改查 1、添加数据 INSERT INTO 表名[(字段名[,字段名]…)] VALUES (值的列表); --[]表示里面的内容可选添加数据分为插入数据记录和插入查询结果 插入数据…

【Vuforia+Unity】AR判断当前平台获取点击/触摸坐标点选中识别的二维码跳转网页

实现了:【VuforiaUnity】判断当前平台获取点击/触摸坐标点选中识别的二维码跳转网页 using UnityEngine; using Vuforia; public class BarcodeScanner : MonoBehaviour { public TMPro.TextMeshProUGUI barcodeAsText; string platformNum""; privat…

Java研学-RBAC权限控制(一)

一 权限控制 1 介绍 RBAC(Role-Based Access Control,基于角色的访问控制)是一种流行的权限控制策略,用于实现复杂系统的安全访问管理。它通过将权限与角色相关联,而不是直接与用户相关联,从而简化了权限管…

《QT实用小工具·二十三》 Ntp校时类

1、概述 源码放在文章末尾 该项目实现了 Ntp校时类 ,包含如下功能: 可设置Ntp服务器IP地址。 推荐用默认的阿里云时间服务器 ntp1.aliyun.com 收到时间信号发出。 时间精确到秒。 下面是demo演示: 项目部分代码如下: #if…

组态王与美国罗克韦尔AB PLC之间无线通讯方案详解

组态王与多台美国罗克韦尔AB PLC间的无线通信测试需要用到以下设备: 三菱PLC型号:FX5u 2台 上位机:组态王6.55 1台 达泰欧美系PLC无线通讯终端——DTD418MB 3块 主从关系:1主2从 通讯接口:RJ45接口 供电&…

传统前端 JS 开发者有福了

大家好,春天的百花绽放之际,各个行业也迎来了各自的新生与挑战。有的继续沉下心来夯实基础,有的大力发展出海业务,又或者通过顶级促销套路天女散花般地贩卖高仿保时捷……这厢 Mendix 各位技术小伙伴继续紧跟时代脉搏,…