社交认证提供商不返回用户邮箱时的用户识别及去重方案咨询
问题描述
这是一个架构层面而非技术实现层面的问题。我们的网页端与移动端应用完全依赖社交认证,目前接入了Google、Facebook等多家社交认证提供商。
用户登录成功后,Google、Facebook等提供商会返回包含邮箱和唯一id的用户数据,我们会将这类数据按如下格式存储在数据库中:
+----+--------------------------------------------------------------+---------------+----------+ | id | socialId | email | provider | +----+--------------------------------------------------------------+---------------+----------+ | 1 | $2a$12$Qx.FVkgYkXqJGF4PyJ1kb.JlSDe9bV6TJFodpTx2eBsYxvqn6Gywa | a@example.com | Facebook | +----+--------------------------------------------------------------+---------------+----------+ | 2 | $2a$12$N2fCTRxymPlcaID5oP617OJTXkrvKAHZ/taFJ.lePZddfW3E6U.Fe | b@example.com | Google | +----+--------------------------------------------------------------+---------------+----------+
上述数据库所有字段均为必填非空字段。
*注:*出于安全考虑,我们对socialIds进行哈希后再存储;存储邮箱的作用是识别用户为新用户还是老用户,避免出现重复记录。
但目前存在问题:部分社交认证提供商不会返回用户邮箱,导致我们无法识别用户新老身份,同时存在生成重复数据行的风险。
请问该问题的最优解决方案是什么?将socialId以原始形式存储在数据库中是否是合理方案?
解答
最优解决方案
你当前的核心问题是身份判重逻辑设计不合理,邮箱本身就不是跨社交提供商的可靠唯一标识,调整逻辑完全可以避开对邮箱的依赖:
- 第一步调整数据库表结构:将
email字段从「非空必填」改为「可空」,放弃用邮箱作为判重依据的逻辑 - 第二步新增
provider+socialId联合唯一索引:每个社交提供商返回的用户socialId在其自身体系内是全局唯一的,二者组合可以唯一标记一个用户,数据库层面的唯一约束也能从根源上杜绝重复行生成 - 第三步调整新老用户判断逻辑:用户登录回调时,先将本次拿到的明文socialId用你现有固定盐值做哈希,再用
哈希后的socialId + provider作为条件去数据库查询,存在匹配记录则为老用户直接登录,不存在则为新用户走注册流程 - 若你的业务强依赖用户邮箱,可以在新用户首次登录时增加引导补填邮箱的流程,校验通过后再写入数据库即可
明文存储socialId的合理性判断
首先明确:socialId只是第三方社交平台分配的公开用户唯一标识,不属于用户敏感信息,就算泄露也不会直接导致账号被盗风险(社交登录的校验核心是第三方返回的签名凭证,而非单纯的socialId)。
- 如果你没有和对应社交平台做额外业务对接的需求(比如拉取用户好友列表、定向推送消息等),继续保持哈希存储完全没问题,上述方案不需要用到原始socialId就能正常运转
- 如果你确实有需要用到原始socialId的业务场景,明文存储是完全合理的,只要做好数据库的权限管控、避免数据泄露即可,不存在安全合规问题
内容的提问来源于stack exchange,提问作者Ven Nilson
相关产品推荐
相关产品推荐

