安全秘密存储(Secure Secrets Storage)

本模块教你安全存储和保护应用秘密(密码、加密/API 密钥、OAuth 令牌)。你将理解秘密是什么、要防止谁访问(包括遵循最小权限原则防止管理员访问),然后用平台功能安全存储——命名凭据避免硬编码、托管包分发秘密、受保护的自定义设置和自定义元数据类型隐藏敏感值;最后用 Apex Crypto 类实现加密/解密、哈希摘要、消息认证码(MAC)和数字签名,并强调加密开发需专业安全审查。...

📅 2026/10/13 ✍️ ponybai 🏷️ salesforce, headless

一、开始使用秘密保护(01 Get Started with Secret Protection)

slide_2
slide_3

本单元建立秘密保护的基础——什么是应用秘密、你要防止谁访问它们,以及为什么某些秘密连管理员都不应看到。学完本单元你将能够:

  • 解释什么是应用秘密;
  • 解释你需要防止谁访问秘密;
  • 列出把应用秘密暴露给 Salesforce 管理员的三种风险。

什么是秘密?(What Are Secrets?)

slide_4

几乎每个应用都会处理某种敏感数据——无论是用户登录应用时输入的密码,还是保护静态数据的加密密钥。这些被称为应用秘密(application secrets)。如果攻击者或恶意用户获得了秘密,就能用它访问机密信息或系统。

常见秘密示例——可用于验证用户特权的数据:

  • 密码和口令(passwords/passphrases);
  • 加密密钥和 API 密钥;
  • OAuth 令牌。

除这些外,你的业务还可能把其它形式的数据视为秘密并施加额外保护,例如监管要求加密某些用户数据。

如上图所示,登录页与 2FA 密钥图标,象征验证用户特权所需的秘密。

你在保护秘密免受谁的侵害?(Who Are You Protecting Secrets From?)

slide_5

知道了要保护什么,接着考虑要防止谁访问这些信息。你也许想到外部攻击者——保护敏感数据免受试图闯入 Salesforce 实例的攻击者侵害。但还要考虑把秘密暴露给其他用户的风险,包括 Salesforce 管理员、AgentExchange 开发者和客户。

考虑这些场景:

  1. 用户不小心下载了恶意软件,Salesforce 会话被攻破;
  2. 一名被裁的员工仍能访问公司系统;
  3. 一个 Communities CRM 用户发现自己有特权 API 访问。

在每种场景中,未妥善保护的秘密都可能暴露给不应访问它的人。因此要保护秘密免受这几类用户侵害:标准用户(普通许可证和平均权限)、外部用户(降低的权限,可能用 Communities 许可证或经 Force.com 站点看数据)、有管理访问的管理员用户(普通许可证但高于平均权限,最高 Modify All Data)。记住:并非每个秘密都需要防住每类用户。

为什么要保护秘密免受管理员侵害?(Why Protect Secrets from Admins?)

slide_6

管理员比普通用户处于更高信任的位置,因为他们对系统的访问级别更高。遵循最小权限原则:只授予用户、程序或进程执行其职能所需的最少特权。给管理员额外访问加密密钥等看似无害,但要考虑:

  1. 如果存储的秘密是外部服务的密码,Salesforce 管理员可能无权直接访问该服务——为保护该服务,要确保他们无法访问密码;
  2. 存储的秘密可能是任何用户(包括管理员)都无法访问的加密密钥——同样要确保管理员访问不到;
  3. 如果管理员能访问秘密,攻击者可以尝试通过攻破管理员账户来获取秘密。

仅仅因为某人能访问某样东西,并不意味着他应该访问!

二、用平台功能保护秘密(02 Protect Secrets Using Platform Features)

slide_7
slide_8

本单元学习存储和保护秘密的平台功能——命名凭据、受保护的自定义设置和受保护的自定义元数据——以及托管包如何帮助安全分发它们。学完本单元你将能够:

  • 列出在托管包内存储秘密的选项和推荐实践;
  • 创建命名凭据以安全定义 callout 端点及其认证参数;
  • 描述受保护的自定义设置和元数据 API 字段如何存储秘密。

在 Salesforce 中存储应用秘密(Store Application Secrets in Salesforce)

slide_9

Salesforce 平台提供了若干用于存储和保护秘密的功能:

  • 命名凭据(Named credentials);
  • 自定义设置(Custom settings)——受保护、不受保护、非托管和托管;
  • 自定义元数据类型(Custom metadata types)。

每种选项以不同方式限制敏感信息,选择与应用部署方式和威胁模型匹配的方法即可。

命名凭据(Named Credentials)

slide_10

命名凭据是安全管理外部提供方和服务认证值的一种机制。当 callout 把命名凭据指定为端点时,Salesforce 管理所有 Apex callout 的认证,你无需在 Apex 代码里添加额外认证逻辑。创建后,你可以用命名凭据引用替换代码中的硬编码 URL,得到更干净、更简单、更安全的代码。

硬编码秘密虽然直接,但有三大问题:

  1. 任何能查看源码的人都能看到嵌入的秘密;
  2. 秘密更新时必须改动源码中所有实例;
  3. 在应用之间移植这个秘密会带来许多复杂问题。

命名凭据正是解决之道——不必把值硬编码进代码,你引用命名凭据即可像访问普通变量一样访问秘密值。

命名凭据的好处(Benefits of Named Credentials)

slide_11

除了限制对应用秘密的访问,命名凭据还让维护秘密变得轻松:配置好命名凭据后,你随时可以在设置中修改它;代码中引用该秘密的任何实例始终保留更新后的值,因为它们直接引用命名凭据。

秘密轮换时无需改动代码——在中心位置更新一次即可。

在何处使用命名凭据(Where to Use Named Credentials)

slide_12

命名凭据最适合标准的认证协议,如用户名和密码、OAuth 2.0、AWS Signature Version 4 和签名 JWT。但它们并非每个场景的最佳选择:拥有 Modify All Data 或 Author Apex 权限的用户可以修改命名凭据或对其发起 callout,从而访问命名凭据保护的数据,甚至提取凭据本身。

如果你需要防住这些场景——例如独立软件供应商(ISV)构建一个需要私下与你的云服务通信的包——应考虑托管受保护的自定义设置或托管受保护的自定义元数据类型等其它选项。

新的命名/外部凭据功能(New Named/External Credential Functionality)

slide_13

新的命名/外部凭据功能增强了安全性并简化了外部集成:

  • External Credentials(外部凭据):表示 Salesforce 用认证协议与外部系统认证的细节,链接到权限集、配置文件和可选自定义头;
  • Named Credentials(命名凭据):作为到外部系统的逻辑连接,把物理 URL 和认证令牌排除在 Apex 代码和未加密数据存储之外,支持 SecuredEndpoint、PrivateEndpoint、Legacy(已弃用)等类型。

两者协作:先创建 External Credential(指定认证协议和权限集/配置文件),再创建 Named Credential 作为 External Services 的 callout 端点,把外部凭据的认证细节链接到命名凭据。权限集授权用户,Principal 映射用户权限,User External Credentials 存储加密令牌,自定义头可加到两者上以传递额外参数。

安全分发秘密(Secure Distributed Secrets)

slide_14

当组织管理员可以访问相关认证秘密时,命名凭据是理想的 callout 方案。但当你必须防止管理员看到数据、或要在多个 Salesforce 组织间分发秘密时,代码应部署为托管包(managed package)。你可以轻松创建一个免费的 Developer Edition 组织作为打包组织。

从安全角度看,托管包相比非托管包或散落代码有显著优势:

  • 托管包有机制在发现安全漏洞时推送自动更新、补丁和修复;
  • 源码被混淆(除显式暴露的 global Apex 类),业务逻辑无法被意外破坏或恶意篡改后重新分发,也防止包内秘密被看到;
  • 必须定义唯一命名空间,既防止命名空间冲突,也把包与本地命名空间隔离——默认情况下,包内秘密无法被托管包外运行的代码访问。

管理受保护的自定义设置与自定义元数据类型(Protected Custom Settings & Metadata)

slide_15

托管包还解锁了两种用于存储和分发信息的受保护功能:

  • 受保护的自定义设置:可存储几乎任何数据,灵活且暴露到应用缓存;在托管包中,订阅组织无法通过 Apex 或 API 看到它——很适合存某些秘密;
  • 受保护的自定义元数据:字段也能以类似方式存秘密(如 API 密钥),为保密应把可见性设为 Protected 并包含在托管包内。

两者可见性都有四个选项:Public (local)、Protected (local)、Public (managed)、Protected (managed)。前三个选项存储一般数据可行,但组织里每个人都能看到数据值;对敏感数据(如应用秘密),务必使用托管受保护(managed protected)配置。

创建托管受保护的自定义设置(Creating Managed Protected Custom Settings)

slide_16

你可以创建一个名为 District Secrets 的托管受保护自定义设置来安全存储秘密。在 Setup 的 Quick Find 输入 Custom Settings 点击 New,定义 label、对象名、设置类型,并把可见性设为 Protected,点击 Save 后即可添加自定义字段存储秘密。

如上图所示,通过定义 label、对象名、设置类型和可见性来创建受保护的自定义设置。

最后把秘密填进受保护的自定义字段。注意:只有设置定义包含在包中,因此包安装到目标/订阅组织后,你需要用 Apex 或 API 脚本填充秘密。

如何使用托管受保护的自定义设置(How to Use Protected Custom Settings)

slide_17

你可以像引用自定义对象一样引用自定义设置——通过公式字段、Apex 自定义设置方法、SOAP API、验证规则、Flow 等。关键安全细节:对受保护自定义设置的引用只能在同一托管包(同一命名空间)内进行。常用 Apex 方法:getInstance()、getInstance(userId)、getInstance(profileId)、getOrgDefaults()、getValues(userId)、getValues(profileId)。

自定义元数据类型(Custom Metadata Types)

slide_18

受保护的自定义元数据类型也能用来存秘密,与自定义设置类似。主要区别在于:自定义元类型中的数据代表应用的元数据。这往往很有利——想象你在打包组织里开发一个带 example.com 外部 API 集成的应用,需要存 API 密钥。存进自定义字段在你自己 DE 组织里没问题,但把代码和定制迁移到生产时,秘密值不会随变更集一起推送,你得手动插入或写脚本填充。

而用自定义元数据类型,API 密钥被当作普通定制一样随包迁移到生产,无需再手动插入;你也不必为受保护的自定义元类型写 postinstall 脚本。它还支持像自定义对象一样用 SOQL 查询——只是后缀是 __mdt 而非 __c(如 SELECT ... FROM District_Profiles__mdt)。

比较自定义设置与自定义元数据类型(Compare Custom Settings and Custom Metadata)

slide_19

两者都能保护秘密,但有值得注意的差异:

用受保护的自定义设置,当:

  • 秘密需频繁更新并立即可用(元数据类型需入队部署,更新不会立刻生效);
  • 你想指定哪些配置文件和用户能访问哪些秘密(元类型没有自定义设置层级类型那样的粒度)。

用自定义元数据类型,当:

  • 想无需额外配置步骤地部署一个通用秘密;
  • 秘密要轻松迁移(如沙箱/开发环境 → 生产),而自定义设置需管理员写 postinstall 脚本或建页面手动录入。

三、在自定义应用中使用加密(03 Use Encryption in Custom Applications)

slide_20
slide_21

本单元把加密加入你的工具包:了解 Apex Crypto 类提供什么,以及如何在应用中实现加密、摘要、MAC 和数字签名。学完本单元你将能够:

  • 描述 Apex Crypto 类;
  • 解释 Crypto 类和自定义加密的不同用例;
  • 在自己的应用中实现加密。

什么是 Apex Crypto 类?(What Is the Apex Crypto Class?)

slide_22

在 Salesforce 应用中实现加密时,Apex 既给你编写自定义加密函数的灵活性,也让你使用大量预构建函数。本单元学习 Salesforce 通过 Apex Crypto 类提供的用于创建摘要(digest)、消息认证码(MAC)、签名以及加密/解密函数。

Crypto 类的函数对保护通信特别有价值——有效屏蔽机密数据免受窃听、验证消息数据完整且未被修改、验证收发双方的真实性。每个函数支持多种算法,让你在控制解决方案组成的同时,尽量减少保护应用所需的额外工作。

加密与解密以保护机密性(Encryption and Decryption)

slide_23

用 Apex 的 Crypto.Encrypt() 和 Crypto.Decrypt() 函数可以轻松灵活地处理加密与解密,它们支持 AES128、AES192、AES256 算法,对确保应用数据的机密性至关重要。你可以选择自己生成加密密钥,或用 Crypto.generateAESKey(Integer keylength) 方法生成。

同样重要的是保护密钥本身——用上一单元学到的技术,把密钥存储在受保护的自定义元数据类型或受保护的自定义设置中。

哈希摘要以保护完整性(Hash Digests to Protect Integrity)

slide_24

另一个验证数据完整性的有用函数是 Apex 的 Crypto.generateDigest()。它生成单向哈希摘要,支持 MD5、SHA1、SHA256、SHA512 等算法。哈希摘要可用来识别意外的数据损坏(或其它不希望的修改):通过对哈希摘要做比较检查,你能快速发现数据变化——因为重算的摘要与原始摘要不匹配,就确认数据已被修改。这能提醒你数据损坏、意外更改或恶意篡改等事件。

注意:哈希算法在安全性上强度不一。虽然 Crypto 类支持 MD5,但它被认为是一种较弱的哈希算法,Salesforce 建议用 SHA2 或更高来计算哈希摘要。

基于哈希的消息认证码(MAC)以证明真实性与完整性

slide_25

Crypto.generateMac() 方法可用于创建 MAC,支持 HMACMD5、HMACSHA1、HMACSHA256、HMACSHA512 算法。MAC 可配合消息摘要函数设置哈希 MAC(HMAC),HMAC 在 TLS 和 IPSec 协议中用于认证消息发送者、确保消息在传输中未被修改(或拦截)。

HMAC 函数涉及消息摘要和一个共享密钥——发送者用它生成 MAC,接收者用它验证 MAC。因为接收者必须用共享私钥验证 MAC,这就表明了发送者的真实性;随后比较消息摘要,让接收者确认消息在传输中未被修改(即防中间人攻击)。

创建数字签名(Creating a Digital Signature)

slide_26

数字签名用非对称加密确保消息的完整性和真实性,从而无需共享私钥。要生成数字签名,用 Crypto.sign() 函数——它用指定算法和私钥为输入数据创建签名。这样,消息接收者可以用匹配的公钥验证签名数据的完整性,证明是谁签发的消息、内容是否完好。

警告!(WARNING!)

slide_27

加密(包括密钥管理)是一项高风险开发活动。在实现任何加密功能时,务必让有加密经验的应用安全专家详细审查所有工作。加密数据过程中的漏洞可能导致严重的隐私和机密性泄露。


文章来源:Trailhead - Secure Secrets Storage