极客时间架构 1 期:第 11 周 安全稳定 - 命题作业

用户头像
Null
关注
发布于: 2020 年 12 月 06 日

第一题

导致系统不可用的原因有哪些?保障系统稳定高可用的方案有哪些?请分别列举并简述。

引起故障的主要原因

  • 硬件故障

  • 软件 bug

  • 系统发布

  • 并发压力

  • 网络攻击

  • 外部灾害

高可用架构

  • 提高代码可用性

  • 使用服务集群

  • 无状态组件

  • Load Balancing

  • 降级、熔断、限流

  • 数据备份、恢复

  • Failover

  • 异地多活

  • 故障恢复计划

第二题

请用你熟悉的语言写一个用户密码验证函数,Boolean checkPW(String 用户ID, String 密码明文, String 密码密文), 返回密码是否正确 boolean 值,密码加密算法使用你认为认为合适的加密算法。

这题题面太简洁了,我都不知道怎么多写点字了。

通常来说如果两个用户密码相同,那么他们密码的单向散列之后的哈希值也是相同的。因而出现了一种叫“查表法”的算法破解哈希密码,主要的思想就是预计算密码字典中的每个密码,然后把哈希值和对应的密码储存到一个用于快速查询的数据结构中。但是查表法只有在所有密码都以相同方式进行哈希加密时才有效;我们可以通过“随机化”哈希来阻止这类攻击,于是当相同的密码被哈希两次之后,得到的值就不相同了。比如可以在密码中混入一段“随机”的字符串再进行哈希加密,这种字符串被称作盐值。

盐值是可以被暴露,但是要保证每个用户唯一,而且不要太短:

  • 用相同的盐,意味着相同的密码又得到了相同的散列值,无法对抗“查表法”。有些算法包裹了好几层的散列算法事实上是没有意义的。

  • 盐太短,又容易暴力破解,安全性又不够用了

我这里图简单就直接用了 userId 作盐了——userId 即唯一,通常又不至于很短。算法也非常简单直接密码+盐做 md5 散列:

import * as md5 from 'md5'
import express = require('express');
import UserDao from './userDao';

function encrypt(userId: string, plaintext: string): string {
return md5(plaintext+userId);
}

function checkPW(userId: string, plaintext: string, ciphertext: string): boolean {
return encrypt(userId, plaintext) === ciphertext;
}

const app: express.Application = express();

app.post('/register', async (req: express.Request, res: express.Response) => {
const {userId, password} = req.body;
const ciphertext: string = encrypt(userId, password);
const ret: boolean = await UserDao.save({userId, pwd: ciphertext});
res.send(ret);
});

app.post('/login', async (req: express.Request, res: express.Response) => {
const {userId, password} = req.body;
const {pwd: ciphertext} = await UserDao.get(userId);
const isValidUser: checkPW(userId, password, ciphertext);
res.send(isValidUser);
});



用户头像

Null

关注

还未添加个人签名 2017.12.29 加入

还未添加个人简介

评论

发布
暂无评论
极客时间架构 1 期:第 11 周 安全稳定 - 命题作业