【问题标题】:Salesforce REST api using reactor With Spring WebClientSalesforce REST api 使用带有 Spring WebClient 的反应器
【发布时间】:2021-03-04 17:47:48
【问题描述】:

我尝试从 Spring Boot 网络客户端连接 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 exception。

请让我知道我在 post Auth Token 创建方法中缺少什么。

【问题讨论】:

  • 您能提供完整的错误文本吗?
  • @nkrivenko 感谢您的回复,请检查上述错误并告诉我您的建议。

标签: spring-boot salesforce spring-webflux spring-webclient


【解决方案1】:

如果您在 SF 设置中查看您的用户,则底部是登录历史记录。它是否显示任何错误?它甚至可以正常登录并且“只是”在实际 API 调用中死掉吗?

在 JWT 流程中,您不应该将整个令牌作为授权标头发送给 SF。您将从令牌开始,SF 会向您发送一条消息,然后在后续调用中使用“access_token”...https://help.salesforce.com/articleView?id=remoteaccess_oauth_jwt_flow.htm&language=en_us 甚至有 Java 示例。

【讨论】:

  • 非常感谢您的回复。我检查了 url 并收到上述错误。请添加您的建议。提前致谢
  • 超时表明有东西阻止了您的请求。您有需要配置的防火墙吗?代理?此 Java 应用程序中的任何其他标注是否正常工作?您检查了 SF 用户的登录历史记录,是否记录了登录尝试或什么也没有?您可以尝试使用更简单(不太安全)的流程,例如help.salesforce.com/…。你甚至可以在 Postman、curl、SoapUI 中运行它,它不像 JWT 那样棘手。只是为了排除连接问题。 stackoverflow.com/a/53568558/313628中的截图
  • 是的,你是对的,因为防火墙问题它不起作用。一旦它得到修复,它就开始正常工作。非常感谢。
猜你喜欢
  • 2017-10-25
  • 2018-11-22
  • 2019-04-18
  • 1970-01-01
  • 2020-04-29
  • 2020-11-24
  • 2018-04-18
  • 2017-11-06
  • 1970-01-01
相关资源
最近更新 更多