Nest Security
NestJS ·加密和哈希
加密是编码信息的过程。这个过程转换原始信息(明文)到另外一种密文的形式。理想情况下,只有授权方可以将密文转换成明文。加密是一个双向的函数,加密可以被合适的 key 解密。
哈希是通过给定的 key 转换成另外一个值的过程。散列函数基于数学算法创建一个新值。一旦哈希完成,是无法从输出值计算回输入值。
加密
Node 提供了内置的 crypto 模块用于加密和解密字符串、数字、buffers 或流等。
// AES 高级加密系统 (Advanced Encryption System) aes-256-ctr,CTR 加密模式
import { createCipheriv, randomBytes, scrypt } from 'crypto';
import { promisify } from 'util';
const iv = randomBytes(16);
const password = 'Password used to generated key';
// The key length is dependent on the algorithm.
// In this case for aes256, it is 32 bytes.
const key = (await promisify(scrypt)(passport, 'salt', 32)) as Buffer;
const cipher = createCipheriv('aes-256-ctr', key, iv);
const textToEncrypt = 'Nest';
const encryptedText = Buffer.concat([
cipher.update(textToEncrypt),
cipher.final()
])
// 解密 encryptedText
import { createDecipheriv } from 'crypto';
const decipher = createDecipheriv('aes-256-ctr', key, iv);
const decryptedText = Buffer.concat([
decipher.update(encryptedText),
decipher.final()
]);
哈希
推荐使用 bcrypt 或 argon2 哈希库。哈希算法主要有MD4、MD5、SHA。
import * as bcrypt from 'bcrypt';
const salt = await bcrypt.genSalt();
const password = 'random_password';
const hash = await bcrypt.hash(password, salt)
// 比对密码与哈希的密码
const isMatch = await bcrypt.compare(passport, hash);
盐 (Salt) 在密码学中,是指通过在密码任意固定位置插入特定的字符串,让散列后的结果和使用原始密码的散列结果不相符,这种过程称之为 “加盐”。密码不能以明文形式保存到数据库中,否则数据泄露密码就会被知道。而一般的加密方式由于加密规则固定,很容易被破解,安全系数不高(MD5 现已能够破解,不再足够安全。即使破解不了,黑客拿到数据库后,用常用的密码数据集进行匹配,也能拿到用户的密码)。密码加盐的加密方式,能很好的解决这一点。
密码加盐里包含随机值和加密方式。随机值是随机产生的,并且以随机的方式混在原始密码里面,然后按照加密方式生成一串字符串保存在服务器。换言之,这个是单向的,电脑也不知道客户的原始密码,即使知道加密方式,反向推出的加密前的字符串也是真正密码与随机值混合后的结果,从而无法解析用户的真正密码。那么是如何验证密码的呢?当你再次输入密码,会以相同的加盐方式生成字符串(盐要提前记录下来,以便后续密码验证),如果和之前的一致,则通过。而其它用户无法获得这种加密方式:即生成哪些随机数,以什么方式混入进去。
Helmet
通过适当地设置 HTTP 头,Helmet 可以帮助保护应用免受一些众所周知的 Web 漏洞的影响。通常,Helmet 只是14个较小的中间件函数的集合,它们设置与安全相关的 HTTP 头。
CORS
跨域资源共享(CORS)允许从其他域请求资源的机制。在底层,Nest 使用了 Express cors 包。
// REST 版本 1
const app = await NestFactory.create(AppModule);
app.enableCors();
// REST 版本 2
const app = await NestFactory.create(AppModule, { cors: true });
await app.listen(3000);
CSRF 保护
跨站点请求伪造(CSRF or XSRF)是一种恶意利用网站,其中未经授权的命令从 Web 应用程序信任的用户传输。要减轻此类攻击,使用 csurf 软件包。
import * as csurf from 'csurf';
app.use(csurf());
限速
为了保护应用程序免受暴力攻击,通常采取是速率限制。
@Module({
imports: [
ThrottlerModule.forRoot({
ttl: 60, // the time to live
limit: 10, // maximum number of requests within the ttl
}),
],
})
export class AppModule {}