Gun v0.9.92结合SEA使用:未登录时无法存入嵌套数据
没错,这确实是 Gun 结合 SEA(Secure Extension Authentication)时的有意设计,核心原因是 SEA 的安全机制默认会对数据写入操作进行身份签名校验,确保数据的可追溯性和权限控制。
为什么会出现这个错误?
当你通过 user.get() 写入数据时,数据会自动与当前登录用户的 Soul(唯一身份标识)绑定,写入操作会用用户的密钥签名,所以能正常执行。而执行 user.leave() 退出登录后,当前 Gun 实例不再持有有效的用户身份,此时调用 gun.get() 写入数据时,SEA 会检查该节点是否允许未签名写入——默认情况下,Gun 的 SEA 配置是要求所有写入操作都要有合法 Soul 签名的,因此就会抛出 "NO! Soul is not signed at 'level1'. " 这个错误。
如何实现存储非用户绑定的公开数据?
如果你需要存储不与特定用户绑定的公开数据,可以通过以下几种方式调整配置或代码:
允许未认证写入公开数据
初始化 Gun 实例时,通过sea.free参数开启未认证写入权限,这样未登录用户也能写入不需要身份绑定的数据:const gun = Gun({ sea: { free: true }, // 开启未认证写入权限 // 其他配置(如 peers 等)... });注意:这个设置会降低整体安全性,只建议用于完全公开、不需要权限控制的数据节点。
写入时跳过签名校验
在调用put方法时,显式传入{soul: null}参数,告诉 SEA 该数据不需要绑定任何 Soul,跳过签名校验:gun.get('mydata').get('level1').get('level2').put('yup', { soul: null });这个方法更灵活,可以针对特定节点开放写入权限,而不是全局关闭安全校验。
使用匿名身份写入
如果你不想完全放弃签名机制,可以生成一个临时的匿名身份,让未登录用户以匿名身份写入数据,这样既保留了数据的可追溯性,又允许未登录操作:// 生成临时匿名身份密钥对 const anonymousIdentity = await Gun.SEA.pair(); // 使用匿名身份写入数据 gun.get('mydata').get('level1').get('level2') .put('yup', { soul: anonymousIdentity.pub });
额外注意事项
如果你的 Gun 实例连接了远程节点,需要确保远程节点的配置也允许未认证写入或对应节点的权限设置一致,否则远程节点会拒绝你的写入请求。
内容的提问来源于stack exchange,提问作者Stef de Vries

