写点什么

高可用方案及密码检查

用户头像
garlic
关注
发布于: 2020 年 12 月 06 日
高可用方案及密码检查

高可用方案


  • 导致系统不可用原因


  1. 硬件故障: 服务器故障, 磁盘故障, 网络故障

  2. 软件 BUG:应用程序 BUG, 中间件 bug, 操作系统 BUG

  3. 系统发布:生产发布由于环境不一致或其他原因导致的投产失败。

  4. 并发压力:高并发压力

  5. 网路攻击:黑客攻击

  6. 外部灾难:各种自然灾害或者战争。 

提升可用性


  • 高可用架构方案

  1. 解耦:软件设计时考虑高内聚,低耦合;

  2. 隔离:根据业务设计的子系统,实现物理隔离;服务层面隔离如:微服务;使用消息队列隔离相互依赖系统:生产者、消费者;虚拟机与容器隔离:不同业务部署在不同虚拟机,容器中; 

  3. 异步:多线程,支持并发; 反应式,事件驱动异步,异步通讯,减少事件依赖,实现无状态服务。

  4. 备份:集群设计,数据库复制,存储复制,冗余策略;

  5. 失效转移: 负载均衡, 数据库主主失效转移;

  6. 服务超时处理: 可以通过幂等,也可以进行事务补偿。当交易超时,异常时一个策略是同样的请求,再发送一次, 一个策略是撤销掉再重新请求;

  7. 重试: 上游调用超时时间要大于下游系统超时调用时间;

  8. 限流: 通过计数器,令牌桶,漏洞算法进行流量控制。令牌桶进入的的时候就控制, 漏斗桶先接收再均匀输出。 也可以使用 PID 控制器根据机器性能的实时调整限制流量。

  9. 降级: 停止部分非核心功能保证核心模块运行。

  10. 异地多活:异地多数据中心, 难点是数据一致性。 


  • 高可用运维方案


  1. 自动化测试:代码上线前进行严格测试,当系统功能越来越完善后, 自动化测试更高效的完成。

  2. 自动化部署:减少人工操作, 部署步骤简单

  3. 持续部署:持续集成, 持续交付, 持续部署;通过自动化测试,自动化部署支持,完成持续部署;

  4. 预发布验证: 通过使用专用服务器,负载策略将一部分交易切入新应用,验证无问题后, 再完成线上系统的更新。 

  5. 版本控制: 分支开发,主干发布;

  6. 自动化发布:发布前也需要 QA, 安全, DBA 确认审核方可上线。

  7. 灰度发布:对于大规模服务,集群分组发布,验证完成后再进行下一组。

  8. 网站监控: 监控用户行为日志, 性能, 业务运行数据

  9. 监控管理:报警信息推送, 自动控制:如自动扩容, 自动限流, 自动失效转移。


  • 高可用方案价值观

  1. 保持简单,整个系统对外提供的服务简单易用, 能快速发现问题, 解决问题

  2. 目标明确,要考虑目前系统实际情况,适当进行裁剪。

  3. 价值回归,成本和收益要合理


密码检查


问题:

用户密码验证函数:

Boolean checkPW(String 用户 ID,String 密码明文,String 密码密文)

返回密码是否正确 boolean 值,密码加密算法使用你认为合适的加密算法


处理流程:  


  • 存储密码

  1. 使用 CSPRNG 生成盐值;

  2. 将盐值添加到密码中,使用标准的密码 hash 函数(Argon2, bcrypt, scrypt, or PBKDF2.)进行处理;

  3. 保存盐值和生成的 hash 值存放到应用数据库


  • 验证密码

  1. 从应用数据库取出盐值和 hash 值;

  2. 将盐值添加到要验证的密码中,使用 hash 函数进行处理,生成 hash 值;

  3. 比较生成的 hash 与数据库记录的 hash 值是否一致,如果匹配密码正确,否则密码错误;


随着硬件计算速度不断发展,出现的 GPU ASIC FPGA, 需要要注意:

  • 加盐不能太短

  • 选择慢 hash

从而增加密码破解难度。


针对盐值:

  • 应当使用 CSPRNG,比较一般的随机数生成有更高的随机性,且完全不可预测

  • 用户间盐值不要复用,修改密码前后更新盐值。

  • 盐值一般存储在用户账户表中。


使用 pbkdf2 算法,迭代次数建议 10000 以上:

import secretsimport hashlib,binascii
class user: def __init__(self): self.id = '1' self.passwd = '' self.salt = ''
def get_salt(): n = 16 salt = secrets.token_bytes(n) return salt
def check_passwd(user, passwd): dk = hashlib.pbkdf2_hmac('sha256',passwd, user.salt,10000) return binascii.hexlify(dk) == user.passwd
def init_user_info(user): passwd = str.encode('1234%Wwerw0') user.salt = get_salt() dk = hashlib.pbkdf2_hmac('sha256', passwd, user.salt,10000) user.passwd = binascii.hexlify(dk)
init_user_info(user)
passwd=str.encode('1234%Wwerw0')print(check_passwd(user, passwd))
passwd=str.encode('123456')print(check_passwd(user, passwd))
复制代码


PBKDF2 对应有 PBKDF1,PBKDF2 散列过程中使用了 PRF,使得密钥每次都参与运算, PBKDF1 只是在首次通过密码和盐值进行运算。

https://en.wikipedia.org/wiki/PBKDF2


另外还有 Scrypt, Argon2


Scrypt 的实现


import secretsimport scrypt,binascii

class user: def __init__(self): self.id = '1' self.passwd = '' self.salt = ''

def get_salt(): n = 16 salt = secrets.token_bytes(n) return salt

def check_passwd(user, passwd): dk = scrypt.hash(passwd, user.salt, N=16384, r=8, p=1) return binascii.hexlify(dk) == user.passwd

def init_user_info(user): passwd = str.encode('1234%Wwerw0') user.salt = get_salt() dk = scrypt.hash(passwd, user.salt, N=16384, r=8, p=1) user.passwd = binascii.hexlify(dk)

init_user_info(user)
passwd=str.encode('1234%Wwerw0')print(check_passwd(user, passwd))
passwd=str.encode('123456')print(check_passwd(user, passwd))
复制代码


Argon2 的实现 Argon2 模式使用随机的 Salt


import argon2

ph = argon2.PasswordHasher(time_cost=2, memory_cost=102400, parallelism = 8, salt_len = 16, hash_len = 16, encoding='utf-8', type=argon2.Type.ID)
class user: def __init__(self): self.id = '1' self.passwd = '' self.salt = ''

def check_passwd(user, passwd): try: ret = ph.verify(user.passwd, passwd) except: ret = False return ret else: return ret

def init_user_info(user): passwd = '1234%Wwerw0' dk = ph.hash(passwd) user.passwd = dk

init_user_info(user)
passwd='1234%Wwerw0'print(check_passwd(user, passwd))
passwd='123456'print(check_passwd(user, passwd))
print(ph.check_needs_rehash(user.passwd))

复制代码


pip3 install argon2-cffi


使用更加安全的方式是, 对于用户密码 hash 值进行加密一般使用对称密钥, 如 AES 等, 可以通过硬件加密,如专用加密设备, 商用加密机,YubiHSM, 如果使用软件加密要防止黑客通过 SQL 注入等手段访问到加密密钥。


参考及引用



架构师训练营作业-李智慧老师相关讲义

图片:https://www.thesslstore.com/blog/difference-encryption-hashing-salting/

https://en.wikipedia.org/wiki/Web_service

https://philcalcado.com/2017/08/03/patternservicemesh.html

https://en.wikipedia.org/wiki/PBKDF2

Microservices Best Practices for Java


用户头像

garlic

关注

还未添加个人签名 2017.11.15 加入

还未添加个人简介

评论

发布
暂无评论
高可用方案及密码检查