做聊天项目的时候,通常会用到关键词过滤。对于一些敏感信息,可能还会进行内容加密。这里从两个不同的功能点,总结下过程。也是在别人的基础上,跑了一遍而已。照着做,可以一步到位。
环境
1. php
2. js
3. laravel
敏感词过滤
https://github.com/FireLustre/php-dfa-sensitive
composer require lustre/php-dfa-sensitive
# 项目中
use DfaFilter\SensitiveHelper;
# 添加词库,使用文件
$path = storage_path('sensitive/words.txt');
$handle = SensitiveHelper::init()->setTreeByFile($wordFilePath);
# 添加词库,单个添加
$data = [
'哎呦我的天',
'太阳',
'太阳块融化我的脸'
];
$handle = SensitiveHelper::init()->setTree($data);
# 替换,检测
$islegal = $handle->islegal($content);
$content = '啥啥啥,哎呦我的天呀,太阳快融化我的脸';
$content = $handle->replace($content, '*', true);
上边这些,github
上都有,照着做就可以了。
https://www.zkii.net/tech/php/1115.html
数据加密解密
这里数据加密使用 aes。数据加密解密的对象是字符串。无论哪 js 还是 php,都可以互相转换。不过这里可能存在一种文体,js 加密的 js 可以解密,但 php 不能解密。反之亦然。出现这种情况,往往是加密解密模式没有配对上。
** js 加密解密 **
参考: https://blog.csdn.net/yingbaoyu/article/details/95761177
如果不是 node 环境,可以下载 https://pan.baidu.com/s/1Mvg8vhlD56wvS4b6yjUoaA 提取码:57gd
例子:
const aseKey = 'YjKp7COQ9QZN2EgMJdiI8tzBsJarvQAr';
const aseIv = 'zmtuC5UyMfK3r1QYXKa1lYmNNy8F5jiP';
//将秘钥转换成Utf8字节数组
const key = CryptoJS.enc.Utf8.parse(aseKey);
const iv = CryptoJS.enc.Utf8.parse(aseIv);
let data = {
name: 'vini',
gender: 1
}
data = JSON.stringify(data);
let encoded = CryptoJS.AES.encrypt(data, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString();
console.log(encoded);
let uncoded = CryptoJS.AES.decrypt(encoded, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
}).toString(CryptoJS.enc.Utf8);
console.log(uncoded);
# 这个时候, data 应该等于 uncoded
key 的长度决定了 CBC 模式的不同。
# php 加密解密
<?php
namespace App\Helper;
class Aes
{
static public function encrypt($data)
{
$method = 'AES-256-CBC';
$key = 'YjKp7COQ9QZN2EgMJdiI8tzBsJarvQAr';
$iv = 'zmtuC5UyMfK3r1QY';
return openssl_encrypt($data, $method, $key, 0, $iv);
}
static public function decrypt($data)
{
$method = 'AES-256-CBC';
$key = 'YjKp7COQ9QZN2EgMJdiI8tzBsJarvQAr';
$iv = 'zmtuC5UyMfK3r1QY';
return openssl_decrypt($data, $method, $key, 0, $iv);
}
}
这里为了方便,把 method key iv 都写死了。项目里边不会这样做。比如,可以定义一个类:
<?php
namespace App\Utils;
class Aes
{
protected $aesSecret = 'YjKp7COQ9QZN2EgMJdiI8tzBsJarvQAr', $aesIv = '00000000000000000000000000000000';
/**
* 进制转换
* @param string $hex
* @return string
*/
protected function aesHexIv($hex = '')
{
$string = '';
$hex = $hex != '' ? $hex : $this->aesIv;
for ($i = 0; $i < strlen($hex) - 1; $i += 2) {
$string .= chr(hexdec($hex[$i] . $hex[$i + 1]));
}
return $string;
}
/**
* AES加密
* @param string $content
* @param string $key
* @param string $hex
* @return string
*/
public function aesEncrypt($content = '', $key = '', $hex = '')
{
$hash = hash('sha256', $key ?: $this->aesSecret, true);
$enCrypt = openssl_encrypt($content, 'AES-256-CBC', $hash, PKCS7_TEXT, $this->aesHexIv($hex));
return base64_encode($enCrypt);
}
/**
* AES解密
* @param string $content
* @param string $key
* @param string $hex
* @return string
*/
public function aesDecrypt($content = '', $key = '', $hex = '')
{
$content = base64_decode(str_replace(' ', '+', $content));
$hash = hash('sha256', $key ?: $this->aesSecret, true);
return openssl_decrypt($content, 'AES-256-CBC', $hash, PKCS7_TEXT, $this->aesHexIv($hex));
}
}
https://www.php.net/manual/zh/openssl.pkcs7.flags.php
更多信息
https://baike.baidu.com/item/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86/468774?fromtitle=aes&fromid=5903&fr=aladdin
https://www.keylala.cn/aes
https://blog.csdn.net/GlatChen/article/details/79978875
https://suijimimashengcheng.51240.com/
进一步了解 aes 加密解密
在多端配合的情况下,不是 key
和 iv
都对,就可以解密出加密的数据的。 秘钥位数,加密模式,填充方式也得一一对应上。
aes 参数
- key length(密钥位数,密码长度)
- key (密钥,密码)
- IV (向量)
- mode (加密模式)
- padding (填充方式)