本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
为 Salesforce 设置 JWT 持有人 OAuth 流程
有关启用与 OAuth 2.0 JSON
创建 PEM 文件的证书/密钥对
创建 PEM 文件的证书/密钥对
openssl req -newkey rsa:4096 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
使用 JWT 创建与 Salesforce 关联的应用程序
登录 Salesforce
,点击右上角的设置齿轮,然后选择设置。 在左侧,导航到应用程序管理器。(平台工具 > 应用程序 > 应用程序管理器)
选择 “新建连接应用程序”。
提供应用名称,让其余名称自动填充。
选中 “启用 OAuth 设置” 复选框。
设置回调网址。它不会用于 JWT,所以你可以使用 https://localhost。
选中 “使用数字签名” 复选框。
上传之前创建的 cert.pem 文件。
添加所需的权限:
通过 API (api) 管理用户数据。
访问自定义权限(自定义权限)。
访问身份 URL 服务(ID、个人资料、电子邮件、地址、电话)。
访问唯一的用户标识符 (openid)。
随时执行请求(refresh_token、offline_access)。
选中为指定用户发放基于 JSON 网络令牌 (JWT) 的访问令牌复选框。
选择保存。
选择继续。
选择管理使用者详细信息。
复制使用者密钥(客户端 ID)。
复制消费者密钥(客户端密钥)。
单击 Cancel (取消)。
生成 JSON 网络令牌 (JWT)
将 key pair 转换为 pkcs12(出现提示时设置导出密码)。
openssl pkcs12 -export -in cert.pem -inkey key.pem -name jwtcert > jwtcert.p12
从 pkcs12 创建 Java 密钥库(出现提示时设置目标密钥库密码,并为源密钥库密码提供以前的导出密码)。
keytool -importkeystore -srckeystore jwtcert.p12 -destkeystore keystore.jks -srcstoretype pkcs12 -alias jwtcert
确认 keystore.jks 包含 jwtcert 别名(出现提示时输入之前的目标密钥库密码)。
keytool -keystore keystore.jks -list
使用 Salesforce 文档中提供的 Java 类 jwteXample 生成签名令牌。
根据需要编辑 ClaimArray 中的值:
ClaimArray [0] = 客户端 ID
ClaimArray [1] = salesforce 用户 ID
ClaimArray [2] = 销售人员登录网址
ClaimArray [4] = 自纪元以毫秒为单位的到期日期。3660624000000 是 2085-12-31。
将 path/to/keystore 替换为密钥库的正确路径.jks。
将密钥库密码替换为您输入的目标密钥库密码
用您输入的源密钥库密码替换私钥密码
编译该代码。该代码依赖于 Apache 共享资源编解码器进行 base6
4 编码。 javac -classpath ".:./commons-codec-1.16.1.jar" JWTExample.java
运行该代码。
java -classpath ".:commons-codec-1.16.1.jar" JWTExample
创建关联的应用程序和 JWT 后,用户仍需要获得应用程序的授权。有关两种方法,请参阅 https://mannharleen.github.io/2020-03-03-salesforce-jwt/ 中的步骤 3。
完成上述步骤后,这将输出一个 JSON 网络令牌 (JWT),该令牌可用于从 Salesforce 获取访问令牌。
示例输入:
export password for pkcs12: awsglue destination keystore password for jks: awsglue source keystore password for jks: awsglue claimArray[0] = “
client-id
”; claimArray[1] = “my@email.com”; claimArray[2] = "https://login.salesforce.com“; claimArray[3] = "3660624000000"; path to keystore: ./keystore.jks keystore password: awsglue privatekey password: awsglue
示例输出:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.
signature
有用的链接:
https://www.base64encode.org/
https://jwt.io/
https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_jwt_flow.htm
JWTExample.java:
import org.apache.commons.codec.binary.Base64; import java.io.*; import java.security.*; import java.text.MessageFormat; public class JWTExample { public static void main(String[] args) { String header = "{\"alg\":\"RS256\"}"; String claimTemplate = "'{'\"iss\": \"{0}\", \"sub\": \"{1}\", \"aud\": \"{2}\", \"exp\": \"{3}\"'}'"; try { StringBuffer token = new StringBuffer(); //Encode the JWT Header and add it to our string to sign token.append(Base64.encodeBase64URLSafeString(header.getBytes("UTF-8"))); //Separate with a period token.append("."); //Create the JWT Claims Object String[] claimArray = new String[5]; claimArray[0] = "
value
"; claimArray[1] = "my@email.com"; claimArray[2] = "https://login.salesforce.com"; claimArray[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300); MessageFormat claims; claims = new MessageFormat(claimTemplate); String payload = claims.format(claimArray); //Add the encoded claims object token.append(Base64.encodeBase64URLSafeString(payload.getBytes("UTF-8"))); //Load the private key from a keystore KeyStore keystore = KeyStore.getInstance("JKS"); keystore.load(new FileInputStream("./keystore.jks"), "awsglue".toCharArray()); PrivateKey privateKey = (PrivateKey) keystore.getKey("jwtcert", "awsglue".toCharArray()); //Sign the JWT Header + "." + JWT Claims Object Signature signature = Signature.getInstance("SHA256withRSA"); signature.initSign(privateKey); signature.update(token.toString().getBytes("UTF-8")); String signedPayload = Base64.encodeBase64URLSafeString(signature.sign()); //Separate with a period token.append("."); //Add the encoded signature token.append(signedPayload); System.out.println(token.toString()); } catch (Exception e) { e.printStackTrace(); } } }