pouchdb-authentication无法配合.sync时,如何实现PouchDB与CouchDB同步?
问题:PouchDB登录远程CouchDB后同步时出现401未授权错误
我能通过pouch-authentication插件在Node实例中登录远程CouchDB,但调用.sync方法进行复制时,不会使用登录凭据,一直收到401未授权/未认证凭据错误。pouch-authentication文档只提到:
"But the pouchdb-authentication API will operate on your remote PouchDB object, not your local one."
请问该怎么实现实时同步?
我的代码如下:
const PouchDB = require("pouchdb"); const PouchDBAuth = require('pouchdb-authentication'); PouchDB.plugin(PouchDBAuth) // 创建本地数据库实例 const localDB = new PouchDB('database') const remoteDB = await new PouchDB("http://127.0.0.1/database", {skip_setup: true}) remoteDB.logIn('user', '12345678', function (err, response) { if (err) { if (err.name === 'unauthorized' || err.name === 'forbidden') { console.log("4", err) } else { console.log("other") } } remoteDB.getSession(function (err, response) { if (err) { // 网络错误 } else if (!response.userCtx.name) { // 当前无登录用户 } else { // response.userCtx.name 为当前登录用户 } localDB.sync(remoteDB, { live: true }).on('change', function (change) { // 数据发生变更! console.log("Yo, something changed") }).on('error', function (err) { console.log("Yo, we got an error", err) // 同步出错!(可能是用户离线?) }); }) })
解决方案
核心问题是:localDB.sync(remoteDB)执行时,同步过程没有自动携带远程DB的认证会话信息。虽然你已经在remoteDB实例上完成了登录,但PouchDB的sync默认不会传递这些凭据,需要显式配置。
方法1:利用会话Cookie配置同步请求头
登录成功后,从getSession的响应中提取会话Cookie,然后在sync的ajax选项里设置请求头,让同步请求携带认证信息:
修改代码如下:
const PouchDB = require("pouchdb"); const PouchDBAuth = require('pouchdb-authentication'); PouchDB.plugin(PouchDBAuth) const localDB = new PouchDB('database') const remoteDB = await new PouchDB("http://127.0.0.1/database", {skip_setup: true}) remoteDB.logIn('user', '12345678', function (err, response) { if (err) { if (err.name === 'unauthorized' || err.name === 'forbidden') { console.log("登录失败:权限不足", err) } else { console.log("登录失败:其他错误", err) } return; } remoteDB.getSession(function (err, sessionResponse) { if (err) { console.log("获取会话失败:网络错误", err) return; } if (!sessionResponse.userCtx.name) { console.log("当前无登录用户") return; } // 提取会话Cookie,用于同步请求的认证 const sessionCookie = sessionResponse.cookie; localDB.sync(remoteDB, { live: true, ajax: { headers: { 'Cookie': sessionCookie } } }).on('change', function (change) { console.log("数据发生变更", change) }).on('error', function (err) { console.log("同步出错", err) }); }) })
方法2:给远程DB实例设置默认认证头
登录成功后,直接将认证信息(比如Basic Auth头)附加到remoteDB的默认AJAX配置中,这样后续所有操作(包括sync)都会自动携带认证凭据:
const PouchDB = require("pouchdb"); const PouchDBAuth = require('pouchdb-authentication'); PouchDB.plugin(PouchDBAuth) const localDB = new PouchDB('database') const remoteDB = await new PouchDB("http://127.0.0.1/database", {skip_setup: true}) remoteDB.logIn('user', '12345678', function (err, response) { if (err) { if (err.name === 'unauthorized' || err.name === 'forbidden') { console.log("登录失败:权限不足", err) } else { console.log("登录失败:其他错误", err) } return; } // 构造Basic Auth头(也可以从登录响应中获取Bearer token,根据CouchDB配置调整) const basicAuth = 'Basic ' + Buffer.from('user:12345678').toString('base64'); // 设置远程DB的默认AJAX请求头 remoteDB.setDefaultAJAXOptions({ headers: { 'Authorization': basicAuth } }); remoteDB.getSession(function (err, sessionResponse) { if (err) { console.log("获取会话失败:网络错误", err) return; } if (!sessionResponse.userCtx.name) { console.log("当前无登录用户") return; } localDB.sync(remoteDB, { live: true }).on('change', function (change) { console.log("数据发生变更", change) }).on('error', function (err) { console.log("同步出错", err) }); }) })
注意事项
- 会话Cookie存在过期时间,生产环境需要处理Cookie过期后的重新登录逻辑
- 如果使用Basic Auth,务必在生产环境使用HTTPS协议,避免明文传输用户名和密码
- Node环境下无需担心跨域问题,若在浏览器环境使用,需确保CouchDB配置允许跨域请求
内容的提问来源于stack exchange,提问作者Averroes
相关产品推荐
相关产品推荐

