创业公司使用AWS Cognito的血泪教训:我不会再选择它
深入剖析一位创业开发者在AWS Cognito认证服务上的真实经历,探讨其文档混乱、版本迭代问题、本地开发困境以及配置限制等痛点,为正在选择身份认证方案的开发者提供有价值的参考建议。
在创业的道路上,每一个技术选型决策都可能决定项目的生死存亡。三年前,当我所在的创业团队决定采用AWS Cognito作为用户身份认证解决方案时,我们满怀信心地认为这是一个稳妥的选择。毕竟,它是AWS生态系统的一部分,而且前五万月活用户免费的政策看起来相当诱人。然而,三个月的深度使用之后,我必须诚实地说:如果时间可以倒流,我绝不会再次选择Cognito。这不是一时冲动的抱怨,而是经过认真思考和反复验证后的肺腑之言。今天,我想把这段经历完整地分享出来,希望能为正在技术选型的开发者提供一些有价值的参考。
整个噩梦的开端,其实比我预想的要早得多。项目启动的第三天,我就意识到事情有些不对劲。当时我正在配置密码重置流程,明明严格按照官方文档的每一个步骤操作,但重置链接却始终跳转到错误的页面。这种情况在正常的开发流程中本不应该发生,毕竟密码重置是一个高度标准化的功能,任何成熟的认证服务都应该能够流畅地支持它。但Cognito却用它独特的方式给我上了第一课:文档的准确性和完整性并不能得到保证。让我来详细说说Cognito的文档问题,这恐怕是我见过的最混乱的技术文档之一。
AWS显然试图用一份文档来满足所有用户群体的需求,结果却是没有人能够得到真正满意的服务。想象一下这样的场景:企业架构师需要深入理解底层的身份协议,期望文档能够详细解释OIDC和SAML的实现细节;前端开发者只想快速实现一个登录界面,期望有清晰的API调用示例;移动端开发者需要了解原生SDK的具体用法,期望能够顺利集成到iOS或Android项目中。这三个需求差异巨大的群体,被迫阅读同一份文档,而文档在不同的章节之间跳跃,假设读者已经掌握了前置知识,却从未明确说明这些前置知识到底是什么。我曾经试图搜索关于Cognito自定义属性验证的内容,结果打开的页面从目录架构开始讲起,假设我已经阅读过四篇我根本不知道存在的文章。整个文档体系就像一张巨大的蜘蛛网,你可以在里面绕来绕去,却永远找不到一条清晰的主线。更让人崩溃的是代码示例的问题。
打开任何一个关于身份验证的页面,你都可能看到三种不同版本的代码:旧版JavaScript SDK的示例、新版Amplify的API调用、还有直接使用AWS SDK的实现方式。这些代码片段之间没有明确的版本标注,你只能通过导入语句来猜测这究竟是哪个版本的代码。这种情况在快速迭代的项目中简直是噩梦,因为当你按照某个示例完成开发后,很可能会在后续的维护中发现这个示例已经过时多年。说到版本问题,就不得不提到Amplify给我带来的第二次打击。当项目刚开始时,Amplify正处在第五版本的稳定期。我基于这个版本编写了完整的认证流程,测试通过后顺利部署上线。
一切看起来都在掌控之中。直到几周后,我注意到控制台出现了一些弃用警告。作为一个负责任的开发者,我决定升级到最新版本以确保项目的长期稳定性。然而,这次升级彻底改变了我对"版本更新"这个词的理解。Amplify从第五版升级到第六版不仅仅是几个方法签名的改变,而是一次彻底的重构。我之前基于第五版构建的整个认证逻辑,包括用户注册、邮箱验证、密码重置等功能,都需要重新编写。
那些我曾经以为已经掌握的API调用方式,在新版中已经完全消失,取而代之的是一套全新的接口设计。官方确实提供了一份迁移指南,但这份指南更像是一份藏宝图,上面标注的地标有一半都已经不存在了。我花了整整两周时间重新学习新版本的API设计理念,然后又一个功能一个功能地迁移代码。这不是升级,这是一场浩劫。本地开发环境的配置更是让我深刻体会到了什么叫做"云计算的局限性"。Cognito本质上是一个纯云端服务,这意味着你无法在本地启动一个实例来进行离线开发和测试。
每次调试认证流程,都需要真实地访问AWS的服务器。这种情况在网络状况良好的办公室里还算可以接受,但当你在咖啡馆遇到不稳定的WiFi,或者在飞机上进行紧急修复时,你就会深刻感受到本地开发环境的价值。更糟糕的是,社区开发了一些本地模拟工具,比如serverless-offline插件和各种Cognito模拟器,但这些工具都是第三方维护的,更新速度远远跟不上官方版本,而且与真实服务的行为存在微妙的差异。这导致了一个可怕的后果:我以为在本地测试通过的代码,到了预发布环境却出现了各种奇怪的问题。本地测试的价值在于尽早发现问题,而Cognito的设计恰恰违背了这个基本原则。自定义能力方面的限制同样让我感到失望。
Cognito提供了一个托管登录界面,表面上看起来可以满足快速上线的需求。但如果你想让这个界面看起来像你自己品牌的一部分,而不是像一个穿着戏服的AWS服务,那你恐怕要大失所望了。能够自定义的内容极其有限:你可以更换Logo,可以修改一些基础的CSS样式,但整个布局结构、交互流程、页面风格都是AWS预设好的,没有商量的余地。社区的建议往往是"自己用SDK构建一个登录界面",这个建议本身没有错,但问题在于,如果最终还是要自己开发整个界面,那托管界面节省的人力成本又在哪里呢?花了大价钱购买了一个你无法真正使用的功能,这种感觉非常糟糕。而压垮我的最后一根稻草,是那次关于邮箱认证配置的经历。我们这个应用只需要邮箱登录功能,用户使用邮箱注册,验证邮箱后设置密码即可。
这是一个极其常见且标准的需求。但当我真正开始配置时,才发现Cognito对于"邮箱"这个概念有着独特的理解。在Cognito的世界里,邮箱既可以是核心属性,也可以是别名,还可以是自定义属性,而这三种身份在系统中的处理方式完全不同。配置选项分散在控制台的多个不同页面中,这些选项之间存在微妙的依赖关系,而官方文档从来没有清晰地解释过这些依赖关系究竟是什么。我在初始配置时犯了一个小错误:把一个应该是标准属性的字段设为了自定义属性。在大多数系统中,这种错误应该可以轻松修正,只需要进入设置页面修改属性类型即可。
但Cognito的答案是:一旦创建为自定义属性,就永远是自定义属性,永远无法更改。这个限制让我陷入了两难境地:要么删除整个用户池从头开始,要么编写一套复杂的迁移脚本,将现有用户迁移到一个配置正确的新用户池中。对于一个已经有实际用户的正式应用来说,"删除重来"根本不是选项。于是我开始编写迁移脚本,处理密码迁移、邮箱验证状态同步、用户属性映射等一系列复杂逻辑。这一切的不便,都源于控制台上一个模糊的选项说明。经历了这一切之后,我开始认真反思这段经历中学到的东西。
技术选型绝对不能只看表面的便利性。"它已经是AWS生态的一部分"这种理由听起来很务实,但完全忽略了工具本身的使用体验对开发效率的影响。免费层级的定价看起来很有吸引力,但如果把这个优惠与为此付出的工程时间成本进行比较,结论往往会让人大吃一惊。在与Cognito搏斗的那些日子里,我花在调试、查文档、重写代码上的时间,如果按照正常的工程师薪资来计算,足以支付一个专业认证服务商好几年的订阅费用。而且最重要的是,这段时间本可以用于产品功能的开发,而不是与基础设施搏斗。对于正在评估Cognito的开发者,我的建议非常简单:先用它构建一个小型的概念验证项目。
不要只是跑通基本的注册登录就下结论,要尝试实现自定义属性的验证逻辑,实现邮箱验证流程,实现密码重置功能,然后计时记录你完成这些功能所花费的时间。统计一下你的文档标签页数量,如果最终打开的标签页超过二十个,那可能需要认真考虑一下这个工具的学习成本是否值得。现在,我们的项目已经太深陷Cognito的泥潭,无法在不造成重大破坏的情况下抽身。每次打开AWS控制台看到那个用户池,我都会感受到一种淡淡的无奈。这就像和一个总是忘记洗碗、不断借用你东西的室友同住:你已经习惯了它的存在,但心里始终有一丝不满。技术选型是一场长期的投入,不应该被短期的便利性所迷惑。
在身份认证这个核心领域,开发者体验和系统稳定性比什么都重要。选择一个文档清晰、API稳定、社区活跃的解决方案,虽然可能需要支付一些费用,但换取的开发和维护效率提升往往远超预期。毕竟,在创业公司的赛道上,时间才是最宝贵的资源,而每一个被浪费在基础设施问题上的小时,都可能是本可以用于产品打磨和用户增长的宝贵时光。 。