选择适合的Node.js授权认证策略
作者:chszs,转载需注明。博客主页:http://blog.csdn.net/chszs
英文原文:https://stormpath.com/blog/choosing-nodejs-authentication-strategy/
Node.js正在兴起!我从2010年就开始使用Node工作,那个时侯我看着它从一个很小的个人项目成长为一个全功能的、能够让现代开发者用于构建真实、重要的大型应用的主要工具。一个完整的解决方案生态系统如雨后春笋般涌现,既帮助了Node开发者,也促使生态系统自身快速演进。但随着它的快速演进,要找到最适合你的解决方案就变得越来越难,因为来自谷歌搜索或npm的噪声太多(译者注:Node.js的第三方库太过庞大,以至于难以选择最适合的)。
授权认证和用户管理尤其是块困难且变化多端的领域。但是,当你用Node创建实际的应用时,它却是你所需的第一个组件。本指南的目的是向你展现用Node如何实现用户管理和授权认证。
Node生态圈有哪些可用选择?
目前Node生态圈在构建用户管理有几种不同的方法。大致上有:
1)Passport.js库或Everyauth库
PassportJS:http://passportjs.org/
Everyauth:https://github.com/bnoguchi/everyauth
2)使用自己的数据库及哈希算法
3)采用“用户管理即服务”的云服务
Passport.js / Everyauth
PassportJS和Everyauth都是Node的授权认证中间件,两者都利用了Connect中间件框架。这意味着如果你使用了Express、Restify或Sails等框架,你可以很容易地将其中任意一个认证中间件(或策略)直接集成到你的应用中。Everyauth只适合嵌入策略,然而PassportJS则可以选择要使用的策略。开发者使用PassportJS通常采取的策略是Facebook和Google,但还包括来自本地的用户名/密码认证,到大量的OpenID、OAuth第三方认证,甚至PassportJS的Stormpath策略。
注:Stormpath是一个用户管理API,它减少了开发时间,提供了即开即用的用户管理基础设施。Stormpath直观的API和专家支持使得开发授权认证、管理、安全的用户和角色变得很容易。
尽管 Everyauth 和 Passport 都建立在同一个中间件框架Connect之上,单他们各有自己的优缺点。Passport 更灵活、更模块化,而Everyauth则提供了额外的功能,支持路由和登录/注册视图。但是很多Node开发者选择了Passport,因为它不使用承诺。
由于 Passport 和 Everyauth 都是建立在 Connect 上的,两者都能帮助你实现会话管理,包括:
1)身份已认证的用户的序列化
2)会话管理
3)注销用户
此外,它们很适用于简单的、简易的用户授权认证,但由于设计上的局限,并不适用于复杂的用户管理需求。你仍然需要设计、实现和维护你的用户管理基础设施的其它部分。
例如,如果你使用的是passport-local策略(此策略需要把授权认证所需的用户名和密码存入你自己的数据库),Passport自身不处理用户的注册及账户的认证。你需要使用数据库模块来进行身份鉴定、创建账户、跟踪认证状态、创建认证令牌、发送邮件,以及验证账户。这意味着开发者会需要考虑URL的安全性、移除过期的令牌,以及其它的安全约束(如数据库中密码的正确散列)。
使用自己的数据库及哈希算法
DIY 的方法不依赖于任何中间件。选择自己的技术栈,用数据库来存储用户信息(可能是 PostgreSQL 或 MongoDB),并使用哈希算法生成密码散列(可能是bcrypt或scrypt)。在npm中搜索bcrypt或scrypt会导致不少模块在质量上的变化,bcrypt或scrypt模块都有自己的依赖集。要特别注意的是,如果你使用Windows开发,我们推荐bcrypt的原生JS实现,见https://github.com/shaneGirish/bcrypt-nodejs。
选定技术栈后,你需要建立用户管理和授权认证。从历史上看,这种方式极其常见,但与其它方式相比,它冗长乏味、易于出错、且需要更多的维护。
你需要增加/解决:
1)账户创建
• 创建用户模式来保持用户数据
• 创建账户及存储使用bcrypt/scrypt散列并加盐后的密码
• 发送带有账户认证令牌的邮件
2)账户授权认证
• 验证用户身份(比较散列值)
3)账户管理
• 密码复位的工作流(产生令牌/让令牌失效)
• 基于角色的访问/许可
4)用ID与第三方社交认证服务商的集成
5)系统安全
• 阻止未授权访问数据库
• 阻止未授权访问操作系统
6)数据备份
授权认证和用户管理的最大的挑战是维护。以密码散列为例,正确的方法是,你基于成本因素选择的哈希算法,为防止暴力攻击特意使散列算法减慢(约300~700毫秒)。但是今天认为是正确的,在明天就可能是不安全的。如果你正在创建的应用程序即将上线,那么你应该每年更换一次散列策略。
尽管Node社区反对这种方式,但这种方式也有一些好处。你可以完全控制自己的基础设施。如果你的工具还没有足够好到可以交付给你的客户、满足复杂的需求,那么你就该向身份认证和用户管理投入人力物力。幸运的是,应用程序和开发者很少有这种需求,所以开源工具以及开放API服务可以帮助我们更快、更好的交付产品。
用户管理即服务
随着时间的推移,软件已经从本地到云端发布,再到分布式API服务。与此同时,开发团队也开始依赖开源软件和开放API服务,甚至和自己的代码一样重要。因此,把自己的用户管理模块卸下来,使用REST API和开放SDK来实现新的用户管理,完成应用程序的开发。Stormpath 支持这种方式。特别是Node社区,已经采取这种面向服务的模式,远远领先于其它语言的任何社区。
通常情况下,API驱动的服务围绕用户管理方面提供了更常规的功能,而且不仅是授权认证。服务供应商还提供了各种额外的功能,通常包括:
1)帐户的电子邮件验证
2)密码重置工作流程
3)基于角色的访问/权限
4)无模式的用户配置文件
5)双重因素身份认证
6)应用程序间的单点登录
7)社交登录的集成(Facebook、谷歌等)
8)与Node的认证中间件如 Passport的集成
除了这些纯粹的功能,它还提供相当可靠的安全性和操作性。为开发者提供了所有基础设施,扩容到吸收用户的流量高峰以及处理用户数据的安全问题。
使用一个API服务通常可以提供更多的便利性和更高的安全性,同时也降低开发和维护的成本。开发人员可以把更多的注意力打集中在自己应用程序的独特部分。
不过有时用户也需要权衡的使用API服务。当你引用一个第三方的依赖性服务到你的应用时,这个第三方服务需要具备高可用、高速、便携性高、能提供传输过程中的高可靠性,并具有足够的灵活性,以满足你的用户数据模型。
可用性和性能是至关重要的,因为对于一个关键系统,用户认证和管理服务是不能离线或变慢的。在SDK缓存并基于现代云计算基础设施是不错的开始,但重要的是,该服务即将面临到最糟糕的情况——例如整个数据中心正在走下坡。因此你想要确保您可以收到任何的通知,则需要建立在用户管理服务的顶部。
https://stormpath.com/resources/security-and-availability/
https://status.stormpath.com/
数据迁移也很关键——你能够安全的把用户数据来回迁移。与轻松写一个脚本把未加密的数据移到JSON上不同,移植密码的难易程度严重依赖于任何已存在的数据的存储方式。例如bcrypt设计的就很容易移植,因为它遵循模块加密格式MCF(Modular Crypt Format)。对很多系统和语言而言,通过查看散列值本身来构造散列是可能的。如果你建立了一个原型,且没有使用 Stormpath之类的服务,我们推荐以bcrypt之类的MCF散列开始——在将来升级时会比较容易。
应用程序和API服务之间的传输安全也是很重要的。额外的网络通讯需要安全化。例如Stormpath 仅支持 HTTPS,使用一个自定义的摘要认证算法来确保,不会被回放和中间人攻击。关于安全性你可以在这里了解更多。https://stormpath.com/resources/security-and-availability/
授权认证服务使用的数据模型很广泛。以Salesforce为例,它的数据模型与Stormpath数据模型有很大的不同。它是基于目录的,因此更通用、更灵活。深入理解这些数据模型是很有价值的,尤其是多承租人应用或者SaaS。此外,API文档变化很大——你应该确保你在努力开始做事之前细致地了解大纲。