新通短信登录
本参考用于负责人明确要求在新项目中接入与 Study Buddy 相同的新通手机号验证码登录时。它复用的是一个独立的服务端身份适配器、本站账号和会话模型;不是把另一个项目的数据库、浏览器 Cookie、上游 token、用户资料、权限或凭据迁移过来。
启用条件与配置
先确认新项目确实获准使用该新通身份服务,并取得该项目/环境独立的服务端配置。不得从 Study Buddy 的环境文件、日志或部署主机复制值。
服务端按环境提供下列配置,并在启动时校验完整性:
XINTONG_BASE_URL
XINTONG_API_PREFIX
XINTONG_ROOT_API_PREFIX
XINTONG_WEB_URL
XINTONG_DEVICE_ID
XINTONG_SCHOOL_ID
它们全部只在服务端读取,不进入 Vite 或其他浏览器构建变量、镜像层、客户端错误或日志。任一配置缺失时,本地身份适配器标记为“未配置”;界面展示账号登录暂不可用,不能渲染看似可以提交的登录表单或转而调用上游。生产与测试使用各自获准的上游环境和本站独立的数据库、存储和 Cookie 上下文。
适配器边界
新增一个本地 IdentityProvider(名称可按项目调整),对外只提供:密码认证、短信发送、短信认证、首次设密和稳定身份资料。浏览器只能调用本站的 /api/identity/*,不直接请求新通接口,也不得得到上游 bearer token。
当前新通协议形态如下;路径、请求头、注册行为和参数以新项目获准的服务合同为准,集中在适配器内部,不能散落在路由或 React 组件中:
- 服务端调用短信验证码发送接口(当前协议为
POST /sms/captcha)。发送前先在本站数据库预占发送额度;上游失败不自动重发。 - 服务端用手机号和验证码调用验证码登录(当前为
POST /user/codeLogin),取得短期上游 token。 - 使用该 token 读取用户资料(当前为 root 路径的
/ieltsbuddy/userinfo),核对手机号,并将稳定上游用户 ID 映射为本站的subject。不能将手机号本身作为账号的唯一身份。 - 若产品保留“短信注册后设置密码”,由适配器检查该上游账号是否已有用户自行设置的密码(当前为 root 路径的
/smarterUsers/select/byId)。尚未设置时才走上游设密接口,随后必须用新密码重新认证确认写入成功。不得将任何供应商的初始密码、固定请求头或项目标识复制到通用代码或浏览器。 - 以
provider ID + subject在本站创建或查找账号,签发本站随机会话。上游 token 仅用于当前服务器操作;短信、验证码和密码均不得写入本站数据库、浏览器存储或日志。
用一个局部的 provider 构造函数接收上述环境值和可注入的 fetch。它应统一处理超时、上游 5xx、非预期 JSON 与业务错误,向本站返回稳定的应用错误码,例如“未配置”“暂不可用”“验证码无效”“短信发送失败”“凭据无效”。不要把上游原始错误正文暴露给用户。
本站会话与首次设密
新项目维护自己的账号表、会话表、限流记录和首次设密记录。可沿用以下经验证的形态:
- 账号会话使用至少 256 位随机 token;数据库只保存 SHA-256 哈希。Cookie 设置为
HttpOnly、Secure(生产环境)、SameSite=Strict,并限制到本站 API 路径。 - 会话有效期和续期策略由新项目明确决定;若采用长期登录,可按实际数据库到期时间滑动续期,且只在本站数据库中续期,不因页面刷新反复调用上游登录。
- 短信验证成功但尚需设密码时,保留一个短期(Study Buddy 为 10 分钟)的一次性设密票据。票据绑定原访客、数据库仅存其哈希;暂存的上游凭据需加密保存,成功升级账号后删除。票据过期、篡改或访客不一致均必须拒绝。
- 首次设密并发执行时锁定对应短期记录。若上游已提交但响应丢失,重试先验证密码已经生效,不能盲目再次覆盖。
- 登出只撤销当前本站会话;是否提供全设备登出是另行明确的产品需求。
如需要保留未登录可浏览、登录后才能执行的体验,使用统一登录拦截层记录被打断的触发元素;登录窗口关闭后恢复仍存在的焦点。业务 API、WebSocket 和写操作仍由服务端强制要求账号,不能信任前端的“已登录”状态。
滥用与成本控制
短信是有成本的外部副作用。用数据库事务在调用供应商前预占配额,使多实例共享计数。Study Buddy 当前的起点是:同手机号 60 秒 1 条、24 小时 5 条;同访客 24 小时 10 条;同供应商 24 小时 200 条;密码登录、验证码校验和设密合计同一身份标识 15 分钟 10 次。新项目应根据供应商成本、目标用户和法规确认是否沿用这些数值;不应完全依赖客户端倒计时。
本站身份接口还应限制请求体、对写请求检查 Origin、设置 Cache-Control: no-store,并使用明确的失败码区分限流、无效验证码、未配置和上游故障。不要把手机号、验证码、密码、上游 token 或完整供应商响应写入诊断。
界面与验收
登录窗至少提供验证码登录;若启用密码登录和首次设密,应使用正确的浏览器输入语义:手机号 autocomplete="username",验证码 autocomplete="one-time-code",已有密码 current-password,首次密码 new-password。验证码输入允许粘贴;客户端倒计时只是提示,服务端限流才是权威。
实现不能止于界面。至少验证:
- 适配器的成功、上游协议错误、超时、资料手机号不匹配、已有密码与首次设密分支;使用可控的 fetch 替身,不记录真实凭据。
- 真实 PostgreSQL 下的本站会话哈希存储、账号隔离、短期票据的过期和绑定、并发限流、重复或丢失响应后的设密恢复。
- 浏览器中的验证码注册/登录、必要的首次设密、退出、密码登录和未登录业务拒绝。
- 仅在负责人明确授权、使用合成手机号并已说明费用时,做一次真实供应商短信验收;自动化通过或 mock 成功不替代这一步。
新项目应在自己的 identity.md 记录获准的服务合同、本站接口、Cookie/会话策略、已完成的验证和仍未做的真实供应商验收。不要将上游协议的猜测、凭据或用户资料写入该文档。