Token认证:如何捕获401/403错误以实现令牌刷新?
捕获PouchDB 401/403错误并刷新令牌的方案
核心思路
PouchDB全局的.onError回调不会触发同步/复制流程中的401/403认证错误,需要从复制操作的事件监听和自定义HTTP请求拦截两个方向针对性处理。
方案一:在复制操作中捕获错误
你配置了live: true和retry: true,这类场景下的认证错误会触发复制对象的error事件,而非全局回调。可以按以下逻辑处理:
// 假设已有实现令牌刷新的函数 const refreshAuthToken = async () => { // 此处编写刷新令牌的业务逻辑,返回新的有效token const response = await fetch('/api/refresh-token'); const data = await response.json(); return data.token; }; // 封装复制启动逻辑 const startReplication = async (authToken) => { const localDB = new PouchDB('local-db'); const remoteDBInstance = remoteDB(authToken); const replication = localDB.sync(remoteDBInstance, { live: true, retry: true }); // 监听复制错误事件 replication.on('error', async (err) => { if (err.status === 401 || err.status === 403) { // 刷新令牌 const newToken = await refreshAuthToken(); // 终止当前复制进程 replication.cancel(); // 使用新令牌重新启动复制 startReplication(newToken); } else { // 处理其他类型的复制错误 console.error('复制异常:', err); } }); }; // 初始化启动复制 startReplication(initialAuthToken);
方案二:自定义HTTP适配器拦截请求
通过重写PouchDB的HTTP适配器,统一拦截所有请求的响应,自动处理令牌刷新和请求重试:
// 保存原始HTTP适配器 const originalHttpAdapter = PouchDB.adapters.http; // 自定义适配器逻辑 PouchDB.adapter('custom-http', (opts, callback) => { const customOpts = { ...opts, // 重写ajax方法实现拦截 ajax: function (ajaxOpts, ajaxCallback) { // 先执行原始请求 originalHttpAdapter.ajax(ajaxOpts, async (err, res) => { if (err && (err.status === 401 || err.status === 403)) { try { // 刷新令牌 const newToken = await refreshAuthToken(); // 更新请求头的Authorization字段 ajaxOpts.headers.Authorization = `Bearer ${newToken}`; // 使用新令牌重新发起请求 originalHttpAdapter.ajax(ajaxOpts, ajaxCallback); } catch (refreshErr) { // 令牌刷新失败,返回错误 ajaxCallback(refreshErr); } } else { // 无认证错误或其他错误,直接返回结果 ajaxCallback(err, res); } }); } }; return originalHttpAdapter(customOpts, callback); }); // 修改远程DB初始化逻辑,使用自定义适配器 const remoteDB = (authToken: string) => { return new PouchDB(remoteDBURL, { adapter: 'custom-http', headers: { Authorization: `Bearer ${authToken}`, } }); };
注意事项
- 处理令牌刷新并发:如果多个请求同时触发401,需添加锁机制(比如用Promise缓存刷新请求),避免重复发起刷新令牌的请求。
- 配合
retry: true时,认证错误触发的自动重试无意义,必须先刷新令牌再重启复制或重新发起请求,否则会陷入无效重试循环。
内容的提问来源于stack exchange,提问作者moamoa
相关产品推荐
相关产品推荐

