簡體   English   中英

用於轉義 html 標簽的 Joi 擴展

[英]Joi extension for escaping html tags

我想創建用於清理字符串輸入和剝離 html 標簽的擴展。

為此,我使用了sanitize-html npm 包。

這是我迄今為止所嘗試的。

const sanitizeHtml = require('sanitize-html');

module.exports = function htmlStrip(joi) {
  return {
    type: 'htmlStrip',
    base: joi.string(),
    messages: {
      htmlStrip: 'Should not contain any html tags.',
    },
    validate(value, helpers) {
      const clean = sanitizeHtml(value, {
        allowedTags: [],
        allowedAttributes: {},
      });
      if (clean) {
        return clean;
      }
      return { value, errors: helpers.error('htmlStrip') };
    },
  };
};

但我得到低於錯誤。

TypeError: Joi.string(...).trim(...).htmlStrip 不是函數

我也嘗試過如下傳遞規則對象,但仍然遇到相同的錯誤。

const sanitizeHtml = require('sanitize-html');

module.exports = function htmlStrip(joi) {
  return {
    type: 'htmlStrip',
    base: joi.string(),
    messages: {
      htmlStrip: 'Should not contain any html tags.',
    },
    rules: {
      htmlStrip: {
        validate(params, value, state, options) {
          const clean = sanitizeHtml(value, {
            allowedTags: [],
            allowedAttributes: {},
          });
          if (clean) {
            return clean;
          }
          return this.createError('string.htmlStrip', { value }, state, options);
        },
      },
    },
  };
};

我正在關注這里提到的文檔。

這就是我使用擴展驗證器的方式。

const Joi = require('@hapi/joi').extend(require('@hapi/joi-date')).extend(require('../utils/sanitize-html-joi'));

const validateAddressCreateData = (data) => {
  const schema = Joi.object({
    address: Joi.string().trim().htmlStrip().required(),
    label: Joi.string()
      .required(),
  });
  return schema.validate(data);
};

不確定為什么您假設Joi.string().trim()類型將與Joi相同,考慮到您擴展Joi對象,但希望htmlStripJoi.string().trim()結果上可用。

兩種類型的簡單 console.log 顯示它們是不同的類型。

console.log(Object.keys(Joi))

[ '_types',
  'alternatives',
  'any',
  'array',
  'boolean',
  ...
  'htmlStrip' ]

console.log(Object.keys(Joi.string().trim()); :

[ 'type',
  '$_root',
  '$_temp',
  '_ids',
  '_preferences',
  '_valids',
  '_invalids',
  '_rules',
  '_singleRules',
  '_refs',
  '_flags',
  '_cache',
  '$_terms',
  '$_super' ]

trim的結果$_super似乎不包含任何鍵,因此它們並沒有真正相關。

我相信如果你想預處理你的輸入然后使用你的htmlStrip ,你必須做這樣的事情:

const sanitizeHtml = require('sanitize-html');

module.exports = function htmlStrip(joi) {
  return {
    type: 'htmlStrip',
    base: joi.string(),
    messages: {
      htmlStrip: 'Should not contain any html tags.',
    },
    validate(value, helpers) {
      const clean = sanitizeHtml(value, {
        allowedTags: [],
        allowedAttributes: {},
      });
      if (clean == value) {
        return { clean, errors: [] };
      }
      return { value, errors: helpers.error('htmlStrip') };
    },
  };
};

這是我如何使用它:

const Joi = require('@hapi/joi').extend(require('@hapi/joi-date')).extend(require('./san'));

const validateAddressCreateData = (data) => {
  const schema = Joi.object({
    address: Joi.htmlStrip(Joi.string().trim()).required(),
    label: Joi.string().required(),
  });
  return schema.validate(data);
};

console.log(validateAddressCreateData({ address: "<body>test</body>", label: "abc"}));

但我不確定輸出是否如您所願:

{ value: { address: '<body>test</body>', label: 'abc' },
  error:
   { ValidationError: Should not contain any html tags.
     _original: { address: '<body>test</body>', label: 'abc' },
     details: [ [Object] ] } }

因此,它似乎根據定義的驗證消息來驗證輸入。 或者你真的想修改正在傳遞的地址 html?

編輯現在明白了,相應地修改了htmlStrip 請參閱比較if(value == clean) 如果消毒劑不需要修剪任何東西,這意味着輸入字符串不包含任何 html 標簽。 其他情況下返回錯誤。

使用自定義驗證導出 Joi 將解決這個問題( custom_joi.js

const sanitizeHtml = require('sanitize-html');
const Joi = require('@hapi/joi')

module.exports = Joi.extend((joi) => ({
 type: "string",
 base: joi.string(),
 messages: {
    "string.htmlStrip": "{{#label}} not contain any html tags"
 },
 rules: {
 htmlStrip: {
  validate(value, helpers) {
    const clean = sanitizeHtml(value, {
      allowedTags: [],
      allowedAttributes: {},
    });
    if (clean == value) {
      return clean;
    }
    return helpers.error("string.htmlStrip")
  }
} } } ) )

並在控制器中導入我們的自定義文件

const Joi = require('../../_helpers/custom_joi');

然后創建驗證模式

const schema = Joi.object().keys({
notes: Joi.string().htmlStrip().allow('', null),
specialInstructions: Joi.string().htmlStrip()
});
const { error, value } = schema.validate(req.body);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM