Leafo/Lapis 框架中的输入验证机制详解

Leafo/Lapis 框架中的输入验证机制详解

lapis A web framework for Lua and OpenResty written in MoonScript lapis 项目地址: https://gitcode.com/gh_mirrors/la/lapis

为什么需要输入验证?

在Web应用开发中,任何来自外部的参数都应被视为不可信输入。开发者有责任在使用这些参数前验证它们是否符合预期格式。常见的需要验证的输入问题包括:

  • 超长输入(如预期几个字符却收到MB级文本)
  • 无效的Unicode序列或不可打印字符
  • 过多的空白字符或不可见字符
  • 类型不匹配(如预期字符串却收到对象)
  • 超出预期的数字范围(如巨大的页码或负数)
  • 不在预设选项范围内的值(如枚举值)
  • 错误地将空字符串视为有效值

Lapis验证模块概述

Lapis框架提供了强大的验证模块,帮助开发者在正式使用输入前确保其正确性和安全性。该模块不仅能验证输入,还能对格式不正确的输入进行转换处理(如去除字符串首尾空白)。

Tableshape验证系统

Lapis目前基于Tableshape库构建了新的验证系统。Tableshape是一个Lua库,用于验证值或对象结构,并具备转换值的能力,可以修复不符合要求的输入。

安装Tableshape

Tableshape不是Lapis的默认依赖,需要单独安装:

luarocks install tableshape

核心验证类型

Lapis在lapis.validate.types模块中提供了一系列Tableshape兼容的类型和类型构造器。

基本使用模式
local types = require "lapis.validate.types"

lapis.validate.types模块的__index元方法已设置为Tableshape的types对象,因此可以直接访问Tableshape提供的所有类型。

关键验证功能

with_params辅助函数

with_params是一个包装器函数,只有当参数通过验证时才会执行后续操作:

local with_params = require("lapis.validate").with_params

app:post("/user/:id", with_params({
  {"id", types.db_id},
  {"action", types.one_of {"delete", "update"}}
}, function(self, params)
  -- 只有参数验证通过才会执行这里
end))
类型构造器
  1. params_shape - 创建适合从参数对象中提取验证值的类型检查器
    • 按指定顺序检查字段
    • 忽略未明确指定的额外字段
    • 返回新的验证后对象
local test_params = types.params_shape {
  {"user_id", types.db_id},
  {"bio", types.empty + types.limited_text(256)},
  {"confirm", types.literal("yes"), error = "请确认"}
}
  1. params_array - 创建从表中提取数组组件的类型检查器

    • 可指定长度范围
    • 可自定义错误前缀
  2. params_map - 创建验证键值对的类型检查器

    • 可自定义错误格式
    • 支持有序迭代
错误处理
  • assert_error - 包装类型检查器,验证失败时抛出错误
  • flatten_errors - 将数组错误转换为单一字符串错误消息

内置验证类型

  1. empty - 匹配nil、空字符串或空白字符串

    types.empty("") --> true
    types.empty("  ") --> true
    
  2. valid_text - 匹配有效的UTF8字符串

    types.valid_text("hello") --> true
    types.valid_text("hel\0o") --> false
    
  3. cleaned_text - 清理无效UTF8序列和非打印字符

    types.cleaned_text:transform("hel\0o") --> "helo"
    
  4. trimmed_text - 去除字符串两端的空白

    types.trimmed_text:transform(" wor ld \t ") --> "wor ld"
    
  5. truncated_text - 截断超长字符串(UTF8感知)

    types.truncated_text(5):transform("hi world") --> "hi wo"
    
  6. limited_text - 限制字符串长度范围

    local limit5 = types.limited_text(5)
    limit5("hi world") --> 超出范围
    
  7. db_id - 匹配适合PostgreSQL序列类型的整数

    types.db_id:transform("2392") --> 2392
    types.db_id:transform("-5") --> 验证失败
    
  8. db_enum - 匹配数据库枚举值

    local statuses = enum { default = 1, banned = 2 }
    local check_status = types.db_enum(statuses)
    check_status:transform("default") --> 1
    

最佳实践建议

  1. 始终验证输入:即使是内部API也应验证所有输入
  2. 使用类型转换:利用验证系统的转换能力规范化输入
  3. 组合验证规则:可以组合多个验证器创建复杂规则
  4. 明确错误消息:为用户提供清晰的验证失败反馈
  5. 考虑性能:对于高频API,验证逻辑应保持高效

通过合理使用Lapis的验证系统,开发者可以大幅提高应用的安全性和健壮性,同时减少因无效输入导致的意外错误。

lapis A web framework for Lua and OpenResty written in MoonScript lapis 项目地址: https://gitcode.com/gh_mirrors/la/lapis

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

田发滔Gwendolyn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值