我正在开发一个使用libsecret的小程序。这个程序应该能够创建一个Secret.Service ...
from gi.repository import Secret
service = Secret.Service.get_sync(Secret.ServiceFlags.LOAD_COLLECTIONS)
...从该服务中获取特定的收藏......
# 2 is the index of a custom collection I created, not the default one.
collection = service.get_collections()[2]
...然后列出该集合中的所有项目,只需打印标签即可。
# I'm just printing a single label here for testing, I'd need all of course.
print(collection.get_items()[0].get_label())
一个重要的细节是收集可能最初被锁定,因此我需要包含检查该可能性的代码,并尝试解锁收集。
# The unlock method returns a tuple (number_of_objs_unlocked, [list_of_objs])
collection = service.unlock_sync([collection])[1][0]
这一点非常重要,因为我最初解锁时,我目前拥有的代码可以完成我所需的全部工作。但是,如果Collection最初被锁定,即使我解锁后,我也无法从里面的Items中获取标签。我可以做的是断开()服务,再次重新创建服务,获得现在解锁的集合,这样我就可以读取每个项目上的标签。另一个有趣的细节是,在读取标签一次后,我不再需要服务重新连接来访问它们。这看起来很不优雅,所以我开始寻找不同的解决方案。
我意识到Collection继承自Gio.DBusProxy,并且该类缓存来自它访问的对象的数据。所以我假设这对我来说是个问题,我没有更新缓存。这很奇怪,因为文档声明Gio.DBusProxy应该能够检测原始对象的变化,但是没有发生。
现在我不知道如何更新该类的缓存。我已经看过一些海马(另一个使用libsecret的应用程序)vala代码,我无法完全解密,我无法代码vala,但提到了Object.emit(方法,我仍然不确定如何使用该方法来实现我的目标。从文档(https://lazka.github.io/pgi-docs/Secret-1/#)我发现了另一个有前途的方法,Object.notify(),它似乎能够发送可以启用缓存更新的更改通知,但我还没有能够正确使用它。
我还在gnome-keyring邮件列表上发布了这个......
https://mail.gnome.org/archives/gnome-keyring-list/2015-November/msg00000.html
...到目前为止还没有答案,并在gnome.org上发现了一个提到这个问题的bugzilla报告......
https://bugzilla.gnome.org/show_bug.cgi?id=747359
......到目前为止(7个月)没有解决方案。
所以,如果有人能够对这个问题有所启发,那就太好了。否则,一些不雅的代码将不幸地发现它进入我的小程序。
编辑-0:
以下是一些在Python3中复制问题的代码。 此代码段会创建一个集合' test_col',其中包含一个项目' test_item',并锁定该集合。注意libsecret将提示您输入此新集合所需的密码:
#!/usr/bin/env python3
from gi import require_version
require_version('Secret', '1')
from gi.repository import Secret
# Create schema
args = ['com.idlecore.test.schema']
args += [Secret.SchemaFlags.NONE]
args += [{'service': Secret.SchemaAttributeType.STRING,
'username': Secret.SchemaAttributeType.STRING}]
schema = Secret.Schema.new(*args)
# Create 'test_col' collection
flags = Secret.CollectionCreateFlags.COLLECTION_CREATE_NONE
collection = Secret.Collection.create_sync(None, 'test_col', None, flags, None)
# Create item 'test_item' inside collection 'test_col'
attributes = {'service': 'stackoverflow', 'username': 'xor'}
password = 'password123'
value = Secret.Value(password, len(password), 'text/plain')
flags = Secret.ItemCreateFlags.NONE
Secret.Item.create_sync(collection, schema, attributes,
'test_item', value, flags, None)
# Lock collection
service = collection.get_service()
service.lock_sync([collection])
然后我们需要重新启动gnome-keyring-daemon,你可以注销并重新登录或使用命令行:
gnome-keyrin-daemon --replace
这将设置您的密钥环,以便我们可以尝试打开最初锁定的集合。我们可以使用此代码段执行此操作。请注意,系统会再次提示您输入之前设置的密码:
#!/usr/bin/env python3
from gi import require_version
require_version('Secret', '1')
from gi.repository import Secret
# Get the service
service = Secret.Service.get_sync(Secret.ServiceFlags.LOAD_COLLECTIONS)
# Find the correct collection
for c in service.get_collections():
if c.get_label() == 'test_col':
collection = c
break
# Unlock the collection and show the item label, note that it's empty.
collection = service.unlock_sync([collection])[1][0]
print('Item Label:', collection.get_items()[0].get_label())
# Do the same thing again, and it works.
# It's necessary to disconnect the service to clear the cache,
# Otherwise we keep getting the same empty label.
service.disconnect()
# Get the service
service = Secret.Service.get_sync(Secret.ServiceFlags.LOAD_COLLECTIONS)
# Find the correct collection
for c in service.get_collections():
if c.get_label() == 'test_col':
collection = c
break
# No need to unlock again, just show the item label
print('Item Label:', collection.get_items()[0].get_label())
此代码尝试两次读取项标签。一个正常的方法,失败,您应该看到一个空字符串,然后使用解决方法,断开服务并重新连接。
答案 0 :(得分:0)
I have been doing this
print(collection.get_locked())
if collection.get_locked():
service.unlock_sync(collection)
Don't know if it is going to work though because I have never hit a case where I have something that is locked. If you have a piece of sample code where I can create a locked instance of a collection then maybe I can help
答案 1 :(得分:0)
我在尝试更新用于从笔记本电脑上的桌面检索密码的脚本时遇到了这个问题,反之亦然。
线索在the documentation for Secret.ServiceFlags
- 有两个:
OPEN_SESSION = 2
在初始化Secret.Service时建立一个秘密转移会话
LOAD_COLLECTIONS = 4
初始化Secret.Service时加载集合
我认为Service
两者加载集合和允许从这些集合中传输秘密(包括项目标签),我们需要使用这两个标志
以下代码(类似于your mailing list post,但没有为调试设置临时集合)似乎可行。它给了我一个项目的标签:
from gi.repository import Secret
service = Secret.Service.get_sync(Secret.ServiceFlags.OPEN_SESSION |
Secret.ServiceFlags.LOAD_COLLECTIONS)
collections = service.get_collections()
unlocked_collection = service.unlock_sync([collections[0]], None)[1][0]
unlocked_collection.get_items()[0].get_label()