如何使用React JS实现跨站点复用已有站点账号登录功能
React栈跨站复用A站账号体系实现方案
你这个是非常典型的单点登录需求,两个站都用React技术栈、且已经有成熟的A站登录服务的前提下,不用重复造账号体系,根据两个站的域名关系选对应方案落地即可,不要自己写非标准的跨域传值逻辑,容易留安全漏洞。
先做前置判断选方案
先确认两个站点的域名关系,两种场景实现成本差很多:
- 同根域名场景:比如A站是
a.xxx.com、B站是b.xxx.com,这种实现成本最低,不需要额外搭复杂授权服务 - 跨根域名场景:比如A站是
a.com、B站是b.com,这种走标准OAuth2.0授权码模式最稳妥,兼容性和安全性都有保障
场景1:同根域名实现步骤
- 先调整A站登录服务的Cookie配置
把存储用户认证态的Cookie作用域设置为根域名.xxx.com,不要绑定A站的单独子域;sameSite属性根据部署情况设为Lax,如果有跨站表单提交需求设为None的话必须同时开启Secure属性(要求HTTPS环境)。 - 给A站加一个通用认证校验接口
比如接口路径为/api/auth/verify,逻辑是读取根域名下的认证Cookie,校验通过就返回当前用户的ID、昵称、权限标识等基础信息,校验失败直接返回401状态码。 - B站React项目做适配
- 封装统一的请求拦截器,在应用初始化、路由跳转前先调用上面的校验接口,拿到用户信息就存在全局状态里(用Zustand、Redux、React Context都可以,沿用你项目原来的选型就行)
- 如果校验接口返回401,直接重定向到A站的统一登录页,地址上带上回调参数
redirect=https://b.xxx.com,告诉A站登完之后跳回B站 - A站登录完成后直接跳回传入的B站地址,这时候根域名下已经有合法的认证Cookie了,B站再调一次校验接口拉取用户信息,就完成登录,全程用户无感知
注意:这个场景下不要把认证Token存在localStorage里,localStorage是严格域名隔离的,跨子域读不到,必须存在根域Cookie下才能两个站共享。
场景2:跨根域名实现步骤(标准OAuth2授权码模式)
不要用前端跨域传Token、JSONP读Cookie这类非正规方案,安全风险极高,直接走标准授权流程:
- 先在A站的账号后台给B站开独立授权接入配置
给B站分配唯一的client_id和client_secret,同时把B站的回调地址(比如https://b.com/auth/callback)加到白名单里,避免非法站点冒用授权。 - B站React侧加登录跳转逻辑
- 检测到用户未登录、或者用户主动点击登录按钮时,直接拼接A站授权页地址跳转,参数带上:
response_type=code&client_id=分配给B站的ID&redirect_uri=B站回调地址&state=自己随机生成的防CSRF字符串 - 这个随机生成的state要存在B站自己的sessionStorage里,等回调的时候做校验用
- 检测到用户未登录、或者用户主动点击登录按钮时,直接拼接A站授权页地址跳转,参数带上:
- A站授权页逻辑
用户跳转到A站授权页时,先校验A站自身的登录态:如果用户没登A站就先展示A站登录表单,登完之后展示授权确认提示(告知用户将使用A站账号登录B站,会同步哪些基础信息),用户确认授权后生成一个有效期5-10分钟、仅可使用一次的授权code,302跳回之前传入的B站回调地址,把code拼在URL参数里带回去。 - B站回调页处理
- 专门给回调地址配一个React路由页面,拿到URL里的code和返回的state,先和之前存在sessionStorage里的state做比对,不一致直接拦截提示安全风险,终止流程
- 校验通过后,把code发给B站自己的后端服务,绝对不要在React前端直接拿code换token,会泄露client_secret
- B站后端拿到code后,带上自身的
client_id、client_secret请求A站的授权换票接口,换取access_token,再拿access_token请求A站的用户信息接口拉取用户数据 - B站后端拿到用户信息后,生成B站自身的登录态(自己的Cookie或者JWT都可以)返回给前端,前端存好登录态就完成整个登录流程
安全提醒:授权code必须设置短有效期、且一次有效,防止被截获后重放冒用;client_secret绝对不能出现在前端代码里,所有和A站授权服务的敏感交互都必须走B站后端代理。
React侧通用适配细节
- 封装路由守卫高阶组件
withAuth,包裹所有需要登录才能访问的业务页面,组件挂载时先检查全局用户状态,未登录就按对应场景的逻辑跳转登录/授权页,不用每个页面单独写校验逻辑 - 单点登出适配:同根域名场景下,登出时直接清理根域名下的认证Cookie即可,两个站的登录态会同时失效;跨根域名场景下如果要做联动登出,A站登出接口要支持传入回调地址,清完A站登录态后跳回B站,B站再清自己的登录态即可
- 本地开发适配:本地调试React项目时,直接在构建工具配置里加接口代理,比如Vite的
vite.config.js、Webpack的devServer里配置代理规则,把A站相关的认证、授权接口代理到测试环境地址,避免本地调试出现跨域问题
内容的提问来源于stack exchange,提问作者Long
相关产品推荐
相关产品推荐

