账户管理, 授权和密码管理往往是很棘手的对很多开发者来说, 账户管理功能是一个暗角, 不会引起足够的重视对于产品经理和用户来说, 产品的最终体验往往超出预期
幸运的是, 谷歌云平台 (GCP) 提供了一些工具, 能够使你在产品创造安全处理和用户账号 (本文中指任何在你系统中注册的人消费者或者内部用户) 认证方面做出更好的决策不论你负责的是什么系统, 部署在 Google Kubernetes Engine 上的 web 网站 Apigee 上的 API 服务使用 Firebase 的应用或者任何包含用户认证的服务, 这篇文章会提供最佳实践, 来保证你拥有一个安全的可伸缩的可用的账户认证系统
1. 对密码字段做哈希处理
对于账户管理, 最重要的原则就是要安全地存储用户的敏感信息, 包括用户的密码用户的数据是神圣的, 必须要适当的处理
任何情况下都不要存储明文密码你的服务中要艺术的哈希处理密码, 并且不能解密密码例如, 使用 PBKDF2, Argon2, Scrypt, or Bcryp 创建这个哈希值应该是对用户唯一的登录凭证加盐处理后的结果不要使用过时的哈希处理技术如 MD5SHA1, 并且在任何情况下都不应该使用可解密的算法或者尝试发明哈希算法
你应该假设你设计的系统最终会被泄露问问你自己如果我的数据今天泄露了, 在使用我的服务或者他们使用的别的服务时, 我的用户的安全和隐私会受到威胁吗? 我们可以做些什么来减轻这种潜在的数据泄露可能造成的危害?
另一个需要考虑的事情: 当用户提供给你密码之后, 如果你能在任何时候产出一个用户的明文密码, 那么你的实现就是有问题的
2. 尽可能允许第三方身份认证
第三方身份认证提供者使你可以依赖一个第三方值得信赖的服务认证用户的身份谷歌 Facebook 和推特通常是可用的提供者
除了已经存在的内部认证系统, 你可以使用一个平台 (如 Firebase 认证) 接入一个第三方的认证服务 Firebase 认证有很多好处, 如管理更简单攻击入口更小和跨平台的 SDK 通过这个列表我们会提出很多好处, 具体查看 案例学习, 这些例子可以让你只需要一天就接入 Firebase 认证
3. 区分用户身份和用户账户的概念
你的用户不是电邮地址他们不是电话号码他们不是由 OAUTH 响应提供的唯一 ID 你的用户是你服务中独有的个性化数据和体验的聚合设计良好的用户管理系统在用户个人资料的不同部分之间具有低耦合性和高内聚性
保持用户帐户和证书的概念分离将大大简化实施第三方认证提供商的过程允许用户更改其用户名并将多个身份链接到单个用户帐户上实际上, 为每个用户提供一个内部全局标识符并通过该 ID 链接其配置文件和身份验证标识可能会有所帮助, 而不是将其全部集中到一条记录之中
4. 允许多个身份关联到单个用户账号
一开始使用用户名和密码认证登录到服务的用户, 后面可能会使用 Google Sign-In 来登录他们并不知道这会创建多余的账号类似地, 由于某些原因, 服务中的一个用户可能会关联到多个电子邮箱如果能正确的分离用户身份和认证信息, 将多个身份链接到同一个用户就会变得简单
你的后台需要考虑到用户可能会通过一部分甚至所有途径来通过注册过程, 但他们并没有意识到在新的第三方身份没有关联到他们已经存在于系统中的账号最简单的实现是要求用户提供一个共同的细节用于识别, 比如电子邮件地址, 电话或用户名等如果该数据与匹配到系统中现有的用户, 则要求他们认证已知身份并将新的 ID 关联到已存在的账号上
5. 不要拒绝长密码或者复杂的密码
NIST 最近更新了关于密码复杂度和强度的准则如果你正在 (或马上会) 使用高强度的散列算法来保存密码, 很多问题就会迎刃而解不管输入的内容有多长, 散列算法都会生成固定长度的输出, 所以用户可以使用他们喜欢的长密码如果你必须限制密码长度, 应该仅从服务支持的最大 POST 大小来考虑限制严格地说, 这通常大于 1M
散列后的密码由大家都知道的一小部分 ASCII 字符组成就算不是, 也很容易通过 Base64 把二进制数据转换过来考虑到这一点, 你应该允许用户在密码中随意使用字符如果有人想在密码中使用克林贡语表情字符和控制字符并在两端加入空白字符, 你应该没有技术方面的理由来拒绝他们
6. 不要为用户名强加不合理的规则
有些网站或服务要求用户名的字符数不低于两三个字符, 不允许不可见字符, 前后不能有空格, 这些都毫无道理然而, 有些网站会要求最小长度为 8 个字符, 只允许使用 7 位(bit) 的 ASCII 字母和数字
在网站上严格限制用户名, 可能会为开发者带来方便, 但在某些极端情况下对用户的要求会让某些用户望而却步
某些情况下最好的办法是指定用户名如果你的服务中遇到这种情况, 需要确保指定的用户名对用户来说很容易想起来也很容易告诉别人字母数字组合的 ID 应该避免视觉上不易识别的符号, 比如 Il1O0 同时还建议对随机生成的字符串进行字典扫描, 确保用户名中没有意外嵌入一些信息这一原则同样适用于自动生成的密码
7. 允许用户更改他们的用户名
在遗留系统或任何提供电子邮件帐户的平台中, 不允许用户更改其用户名是非常常见的这里有很多好的理由支持不自动释放用户名以供重复使用, 但系统的长期用户最终会给出一个很好的理由来使用不同的用户名, 并且他们可能不想创建新的帐户
你可以通过允许别名并让你的用户选择主别名来满足用户期望更改其用户名的愿望你可以在此功能之上应用所需的任何业务规则某些组织可能每年仅允许更改一次用户名, 或将阻止用户显示除主用户名以外的任何内容电邮供应商可能会确保用户在将老用户名从其帐户中分离出来之前充分得了解了相关风险, 或者可能完全禁止将老用户名断开链接
为你的平台选择合适的规则, 但要确保它们允许你的用户随着时间的推移而成长和改变
8. 允许你的用户删除自己的账号
相当数量的服务没有用于用户删除其账户及相关数据的自助服务手段用户永久关闭帐户并删除所有个人数据有很多好的理由这些问题需要根据你的安全行和合规需求进行平衡, 但大多数受监管的环境提供了有关数据保留的具体指导避免合规和黑客攻击的常见解决方案是让用户自己规划其帐户以备将来自动删除
在某些情况下, 你可能需要遵照用户的要求, 及时删除其数据如果发生数据泄露, 对于发生已关闭帐户的数据泄露情况, 你还可以大大提高你的曝光率
9. 在会话长度上有意识地做决定
在安全验证上常常被忽略的是会话长度 Google 作出了一些努力来确保用户的行为并进行双重检查, 这主要基于某些事件和行为用户可以有步骤地进一步加强他们的安全性
你的服务可以有明确的理由来保持会话, 而不是非关键分析目的无限期开放, 但是, 应该有一个门槛来要求您输入密码或第二个因素或其他用户验证
考虑多久的时间用户应该认证, 并明确之前是不活跃的如果有人进行密码重置, 就需要验证所有活动会话的用户身份如果一个用户更改核心方面的配置文件或当他们执行敏感的行动, 应该提示身份验证或第二因素并考虑不允许从多个设备或位置登录是否有意义
当你的服务用户会话到期或需要重复认证, 提示用户实时或提供一种机制来保护任何活动来保存未保存的最后验证用户填写表单, 提交它一段时间后, 发现他们所有的输入已经丢失, 他们必须再次登录, 这是非常令人沮丧的
10. 使用两步校验
考虑在选择两步校验 (也称为双因素授权或仅 2FA) 方法中之后用户账号被盗对用户的实际影响由于多重弱点, SMS 2FA 认证已被 NIST 弃用, 但它可能是你的用户能接受的针对他们认为微不足道的服务时最安全的选择尽你所能提供仅可能的最安全的 2FA 认证启用第三方身份识别提供商并搭载他们的 2FA 是一种简单的可以无需大量开销或经历即可提高安全性的方法
11. 使用户 ID 不区分大小写
你的用户不关心, 甚至可能不记得他们的用户名准确的大小写情况用户名应完全不区分大小写将所有用户名和电邮地址以小写形式存储起来并在比较之前将所有输入转换为小写字母都是很常见的
智能手机所代表的用户设备比例在不断增加他们大多数提供自动更正和自动大写的纯文本字段在 UI 层阻止这种行为可能不是理想的或完全有效的, 并且你的服务应足够健壮以处理无意中地自动大写的电邮地址或用户名
12. 构建安全的身份认证系统
如果你正在使用的诸如 Firebase Auth 这样的服务, 那么很多安全问题都已经自动为你处理了但你的服务将始终需要正确设计以防止滥用核心考量因素包括实施密码重置而不是密码检索详细的帐户活动记录多次失败登录尝试之后锁定账户以及对未识别的设备或长时间处于空闲状态的帐户进行双因素身份验证对安全认证系统来说还有更多细节, 请参阅以下链接以获取更多信息
原 文: 12 best practices for user account, authorization and password management
译 文: 开源中国社区
作 者: Tocy, lee, 边城, 无若 译
来源: https://sdk.cn/news/8117