PythonIDE Docs
中文
简体中文

keychain

iOS 钥匙串安全存储。

iOS 钥匙串:安全保存 token、密码、API Key 等敏感小字符串。

边界:只存敏感凭据,不存主题、筛选条件或大型 JSON(用 storage)。不要把 get_password() 的明文打印到日志或界面;需要展示时用「已配置 / 未配置」或掩码。

#模块概览

说明
导入import keychain
适合做什么登录 token、API Key、私密密码、多账号凭据
调用时机保存/删除放在按钮回调;读取可在启动时,但不要在 body() 里反复读
推荐顺序固定 service + accountset_password → 需要时 get_password → 退出时 delete_password
定位键service 是命名空间(如 myapp.api),account 是用户名或环境名

#快速开始

下面脚本写入、读取、删除一条演示凭据:

python
import keychain

SERVICE = "demo-api"
ACCOUNT = "default"

ok = keychain.set_password(SERVICE, ACCOUNT, "secret-token")
print("保存:", ok)

token = keychain.get_password(SERVICE, ACCOUNT)
print("已配置:", bool(token))  # 不要 print(token) 明文

ok = keychain.delete_password(SERVICE, ACCOUNT)
print("删除:", ok)

for service, account in keychain.get_services():
    print(service, account)

#AppUI 示例

SecureField 收集输入,保存后清空输入框;界面只显示状态,不展示明文 secret。

python
import appui
import keychain

SERVICE = "demo-api"
ACCOUNT = "default"

state = appui.State(
    token="",
    status="未检查",
    message="输入 token 后点保存",
)


def update_token(value):
    state.token = value


def save_token():
    value = state.token.strip()
    if not value:
        state.message = "请输入 token"
        return
    ok = keychain.set_password(SERVICE, ACCOUNT, value)
    state.batch_update(
        token="",
        status="已配置" if ok else "保存失败",
        message="已保存到钥匙串" if ok else "保存失败,请重试",
    )


def check_token():
    token = keychain.get_password(SERVICE, ACCOUNT)
    state.batch_update(
        status="已配置" if token else "未配置",
        message="凭据存在" if token else "尚未保存凭据",
    )


def delete_token():
    ok = keychain.delete_password(SERVICE, ACCOUNT)
    state.batch_update(
        status="已删除" if ok else "删除失败",
        message="凭据已清除" if ok else "没有可删除的凭据",
    )


def body():
    return appui.NavigationStack(
        appui.Form([
            appui.Section("API Token", [
                appui.SecureField("粘贴 token", text=state.token, on_change=update_token),
                appui.Button("保存到钥匙串", action=save_token)
                .button_style("bordered_prominent"),
                appui.Button("检查是否已配置", action=check_token),
                appui.Button("删除凭据", action=delete_token, role="destructive"),
            ]),
            appui.Section("状态", [
                appui.LabeledContent("配置", value=state.status),
                appui.Text(state.message).foreground_color("secondaryLabel"),
            ]),
        ]).navigation_title("钥匙串")
    )


appui.run(body, state=state)

#API 参考

#速查

API作用
set_password(service, account, password)保存或更新 → bool
get_password(service, account="")读取 → strNone
delete_password(service, account="")删除 → bool
get_services()列出本 App 已存的 (service, account)

#读写凭据

条目由 service + account 两个字符串定位:

参数说明
service稳定命名空间,如 openaigithubmyapp.production
account用户名、邮箱或环境名,如 defaultprod
password要保存的 secret 字符串
python
import keychain

keychain.set_password("myapp.api", "prod", "sk-xxx")
token = keychain.get_password("myapp.api", "prod")
if token:
    # 用于请求头,不要打印到界面
    headers = {"Authorization": f"Bearer {token}"}

set_password(...) — 成功返回 True,失败返回 False

get_password(...) — 存在时返回字符串,不存在返回 None。判断用 if token:,不要假设空字符串。

delete_password(...) — 用户退出账号或切换环境时调用。

#列出凭据

get_services() — 返回 list[tuple],每项是 (service, account)

python
for service, account in keychain.get_services():
    print(service, account)

用于设置页的「已保存账号」列表;仍不要直接展示密码明文。

#与 storage 的分工

数据类型推荐模块
主题、筛选、小型 JSONstorage
token、密码、API Keykeychain
大文件、图片文件系统或媒体模块

#常见错误

错误写法后果修正
把 token 存进 storage敏感数据不安全使用 keychain.set_password
print(get_password(...))secret 进入日志只打印 bool(token) 或掩码
每次随机 service旧凭据读不到使用固定命名空间
body() 里读并显示明文刷新时泄露 secret只显示「已配置 / 未配置」

#相关文档

文档用途
storage非敏感偏好设置
network带 token 发 HTTP 请求
biometric生物识别解锁流程
原生能力入口MiniApp 场景配方

#预期效果

运行示例后,界面应出现文档描述的目标结果;若与预期不符,先看「失败路径」并按返回值或日志排查。