【影片教學推薦:node js教學 】
幽默風趣的後端程式設計師一般自嘲為 CURD Boy。 CURD, 也就是某一儲存資源的增刪改查,這完全是面向資料程式設計啊。
真好呀,面向資料編程,往往會對業務理解地更加透徹,從而寫出更高品質的程式碼,造出更少的 BUG。既然是面向資料程式設計更需要避免髒資料的出現,加強資料校驗。否則,難道要相信前端的資料校驗嗎,畢竟前端資料校驗直達用戶,是為了 UI 層更友善的用戶回饋。
後端由於重業務邏輯以及待處理各種數據,以致於分成各種各樣的層級,以我經歷過的後端專案就有分為Controller
、Service
、Model
、Helper
、Entity
等各種命名的層,五花八門。但這裡肯定有一個層稱為 Controller
,站在後端最上層直接接收客戶端傳輸資料。
由於Controller
層是伺服器端中與客戶端資料互動的最頂層,秉承著Fail Fast
的原則,肩負著資料過濾器的功能,對於不合法數據直接打回去,如同秦瓊與尉遲恭門神般威嚴。
資料校驗同時衍生了一個半文檔化的副產品,你只需要看一眼資料校驗層,便知道要傳哪些字段,都是些什麼格式。
以下都是常見的資料校驗,本文講述如何對它們進行校驗:
const body = { id, name, mobilePhone, email }
作者接觸過一個沒有資料校驗層的後端項目,if/else
充斥在各種層級,萬分痛苦,分分鐘向重構。
JSON Schema
基於JSON 進行資料校驗格式,並附有一份規範json-schema.org,目前(2020 -08) 最新版本是7.0。各種伺服器程式語言都對規範進行了實現,如go
、java
、php
等,當然偉大的javascript 也有,如不溫不火的ajv。
以下是校驗使用者資訊的一個Schema,可見語法複雜與繁瑣:
{ "$schema": "http://json-schema.org/draft-04/schema#", "title": "User", "description": "用户信息", "type": "object", "properties": { "id": { "description": "用户 ID", "type": "integer" }, "name": { "description": "用户姓名", "type": "string" }, "email": { "description": "用户邮箱", "type": "string", "format": "email", "maxLength": 20 }, "mobilePhone": { "description": "用户手机号", "type": "string", "pattern": "^(?:(?:\+|00)86)?1[3-9]\d{9}$", "maxLength": 15 } }, "required": ["id", "name"] }
對於複雜的資料類型校驗,JSON Schema 內建了以下Format,方便快速校驗
對於不在內建Format 中的手機號,使用ajv.addFormat
可手動新增Format
ajv.addFormat('mobilePhone', (str) => /^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(str));
joi 自稱最強大的JS 校驗庫,在github 也斬獲了一萬六顆星星。相較於 JSON Schema 而言,它的語法更加簡潔且功能強大。
The most powerful data validation library for JS
#完成相同的校驗,只需要更少的程式碼,並且能夠完成更強大的校驗。以下僅做範例,更多範例請前往文件。
const schema = Joi.object({ id: Joi.number().required(), name: Joi.number().required(), email: Joi.string().email({ minDomainSegments: 2, tlds: { allow: ['com', 'net'] } }), mobilePhone: Joi.string().pattern(/^(?:(?:\+|00)86)?1[3-9]\d{9}$/), password: Joi.string().pattern(/^[a-zA-Z0-9]{3,30}$/), // 与 password 相同的校验 repeatPassword: Joi.ref('password'), }) // 密码与重复密码需要同时发送 .with('password', 'repeat_password'); // 邮箱与手机号提供一个即可 .xor('email', 'mobilePhone')
由於資料直接從路由傳遞,因此koajs
官方基於joi
實作了一個 joi-router,前置資料校驗到路由層,對前端傳遞來的query
、body
與params
進行校驗。
joi-router
也同時基於 co-body
對前端傳送的各種 content-type
進行解析及限制。如限制為 application/json
,也可在一定程度上防止 CSRF 攻擊。
const router = require('koa-joi-router'); const public = router(); public.route({ method: 'post', path: '/signup', validate: { header: joiObject, query: joiObject, params: joiObject, body: joiObject, maxBody: '64kb', output: { '400-600': { body: joiObject } }, type: 'json', failure: 400, continueOnError: false }, pre: async (ctx, next) => { await checkAuth(ctx); return next(); }, handler: async (ctx) => { await createUser(ctx.request.body); ctx.status = 201; }, });
作者在一次排查效能問題時發現,一條 API 竟在資料校驗層耗時過久,這是我未曾想到的。而問題根源在於不安全的正規表示式,那什麼叫做不安全的正規表示式呢?
例如下邊這個能把 CPU 跑掛的正規表示式就是一個定時炸彈,回溯次數進入了指數爆炸般的增長。
可以参考文章 浅析 ReDos 原理与实践
const safe = require('safe-regex') const re = /(x+x+)+y/ // 能跑死 CPU 的一个正则 re.test('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') // 使用 safe-regex 判断正则是否安全 safe(re) // false
数据校验,针对的大多是字符串校验,也会充斥着各种各样的正则表达式,保证正则表达式的安全相当紧要。safe-regex 能够发现哪些不安全的正则表达式。
更多编程相关知识,可访问:编程教学!!
以上是Controller層中Node怎麼進行資料校驗?的詳細內容。更多資訊請關注PHP中文網其他相關文章!