Salesforce REST api 使用 reactor With Spring WebClient
Salesforce REST api using reactor With Spring WebClient
我尝试从 Spring 引导网络客户端连接 Salesforce。我有带有以下代码的 JWT 令牌
String header = "{\"alg\":\"RS256\"}";
String claimTemplate = "'{'\"iss\": \"{0}\", \"sub\": \"{1}\", \"aud\": \"{2}\", \"exp\": \"{3}\", \"jti\": \"{4\"'}'";
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[4];
claimArray[0] = "3MVG99OxTyEMCQ3gNp2PjkqeZKxnmAiG1xV4oHh9AKL_rSK.BoSVPGZHQukXnVjzRgSuQqGn75NL7yfkQcyy7";
claimArray[1] = "my@email.com";
claimArray[2] = "https://login.salesforce.com";
claimArray[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
claimArray[4]=<JTI>
MessageFormat claims;
claims = new MessageFormat(claimTemplate);
String payload = claims.format(claimArray);
token.append(Base64.encodeBase64URLSafeString(payload.getBytes("UTF-8")));
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream("./path/to/keystore.jks"), "keystorepassword".toCharArray());
PrivateKey privateKey = (PrivateKey) keystore.getKey("certalias", "privatekeypassword".toCharArray());
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(token.toString().getBytes("UTF-8"));
String signedPayload = Base64.encodeBase64URLSafeString(signature.sign());
token.append(".");
token.append(signedPayload);
System.out.println(token.toString());
} catch (Exception e) {
e.printStackTrace();
}
根据下面提到的 Salesforce 网站。我的类路径中有私钥 .der 文件。
我已经通过以下代码获得了 AuthToken。
HttpClient client = HttpClient.create();
ReactorClientHttpConnector conn = new ReactorClientHttpConnector(client);
WebClient web = WebClient.builder()
.baseUrl("https://dev.salesforce.com")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.clientConnector(conn).build();
Mono<Token> token = web.post()
.uri("/services/oauth2/token")
.body(BodyInserters.fromFormData("grant_type", "jwt-bearer")
.with("assertion", getAuth()).exchange().flatMap(res->res.bodyToMono(Token.class));
return token;
但我收到 reactor.core.Exceptions$Reactiveexception io.netty.channel.AbstractChannel$AnnotatedConnectionException: connection timedout exception with no further information 异常。
请告诉我在 post Auth Token 创建方法中缺少什么。
如果您在 SF 设置中查看您的用户,底部是登录历史记录。它显示任何错误吗?它是否甚至登录正常并且“只是”在实际 API 调用时死机?
在 JWT 流程中,您不应该将整个令牌作为授权发送给 SF header。您将从令牌开始,SF 会向您发送一条消息,从该消息在后续调用中使用“access_token”... https://help.salesforce.com/articleView?id=remoteaccess_oauth_jwt_flow.htm&language=en_us 甚至有 Java 个样本。
我尝试从 Spring 引导网络客户端连接 Salesforce。我有带有以下代码的 JWT 令牌
String header = "{\"alg\":\"RS256\"}";
String claimTemplate = "'{'\"iss\": \"{0}\", \"sub\": \"{1}\", \"aud\": \"{2}\", \"exp\": \"{3}\", \"jti\": \"{4\"'}'";
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[4];
claimArray[0] = "3MVG99OxTyEMCQ3gNp2PjkqeZKxnmAiG1xV4oHh9AKL_rSK.BoSVPGZHQukXnVjzRgSuQqGn75NL7yfkQcyy7";
claimArray[1] = "my@email.com";
claimArray[2] = "https://login.salesforce.com";
claimArray[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
claimArray[4]=<JTI>
MessageFormat claims;
claims = new MessageFormat(claimTemplate);
String payload = claims.format(claimArray);
token.append(Base64.encodeBase64URLSafeString(payload.getBytes("UTF-8")));
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream("./path/to/keystore.jks"), "keystorepassword".toCharArray());
PrivateKey privateKey = (PrivateKey) keystore.getKey("certalias", "privatekeypassword".toCharArray());
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(token.toString().getBytes("UTF-8"));
String signedPayload = Base64.encodeBase64URLSafeString(signature.sign());
token.append(".");
token.append(signedPayload);
System.out.println(token.toString());
} catch (Exception e) {
e.printStackTrace();
}
根据下面提到的 Salesforce 网站。我的类路径中有私钥 .der 文件。
我已经通过以下代码获得了 AuthToken。
HttpClient client = HttpClient.create();
ReactorClientHttpConnector conn = new ReactorClientHttpConnector(client);
WebClient web = WebClient.builder()
.baseUrl("https://dev.salesforce.com")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.clientConnector(conn).build();
Mono<Token> token = web.post()
.uri("/services/oauth2/token")
.body(BodyInserters.fromFormData("grant_type", "jwt-bearer")
.with("assertion", getAuth()).exchange().flatMap(res->res.bodyToMono(Token.class));
return token;
但我收到 reactor.core.Exceptions$Reactiveexception io.netty.channel.AbstractChannel$AnnotatedConnectionException: connection timedout exception with no further information 异常。
请告诉我在 post Auth Token 创建方法中缺少什么。
如果您在 SF 设置中查看您的用户,底部是登录历史记录。它显示任何错误吗?它是否甚至登录正常并且“只是”在实际 API 调用时死机?
在 JWT 流程中,您不应该将整个令牌作为授权发送给 SF header。您将从令牌开始,SF 会向您发送一条消息,从该消息在后续调用中使用“access_token”... https://help.salesforce.com/articleView?id=remoteaccess_oauth_jwt_flow.htm&language=en_us 甚至有 Java 个样本。