IBM Watson APIs Java SDK 使用 Watson 令牌认证失败

IBM Watson APIs Java SDK use Watson token authentication fail

我用Watson APIs Java SDK and my Authentication was use function setUsernameAndPassword(username, password), but now I want to use Tokens for authentication.

我的"Username and Password"代码

mAssistant = new Assistant("2018-02-16");
mAssistant.setUsernameAndPassword(mUserName, mPassword);
InputData input = new InputData.Builder("Hello").build();
MessageOptions options = new MessageOptions.Builder("{workspaceId}")
                                           .input(input)
                                           .build();
MessageResponse response = mAssistant.message(options).execute();
System.out.println(response);

它工作正常。

我用这个方法来获取我的令牌。 curl -X GET --user "{username}:{password}" "https://gateway.watsonplatform.net/authorization/api/v1/token?url=https://gateway.watsonplatform.net/conversation/api"

身份验证令牌
方法一

mAssistant = new Assistant("2018-02-16");
Map<String, String> map = new HashMap<>();
map.put("X-Watson-Authorization-Token", "{token_string}");
mAssistant.setDefaultHeaders(map);
mAssistant.setSkipAuthentication(true);
InputData input = new InputData.Builder("Hello").build();
MessageOptions options = new MessageOptions.Builder("{workspaceId}")
                                           .input(input)
                                           .build();
MessageResponse response = mAssistant.message(options).execute();
System.out.println(response);

获取错误代码

E/WatsonService: POST status: 403, error: Forbidden
com.ibm.watson.developer_cloud.service.exception.ForbiddenException: Forbidden
05-07 16:05:57.720 10392-10476/mvi.rcu W/System.err:     at com.ibm.watson.developer_cloud.service.WatsonService.processServiceCall(WatsonService.java:401)
05-07 16:05:57.720 10392-10476/mvi.rcu W/System.err:     at com.ibm.watson.developer_cloud.service.WatsonService$WatsonServiceCall.execute(WatsonService.java:459)

方法二

mAssistant = new Assistant("2018-02-16");
IamOptions options = new IamOptions.Builder()
                                   .accessToken(token)
                                   .build();
mAssistant.setIamCredentials(options);
mAssistant.setEndPoint("https://gateway.watsonplatform.net/conversation/api");
// do same ... 
// mAssistant.message(options).execute();
// ...

获取错误信息

W/System.err: com.ibm.watson.developer_cloud.service.exception.UnauthorizedException: Unauthorized: Access is denied due to invalid credentials. Tip: Did you set the Endpoint?
W/System.err:     at com.ibm.watson.developer_cloud.service.WatsonService.processServiceCall(WatsonService.java:398)
W/System.err:     at com.ibm.watson.developer_cloud.service.WatsonService$WatsonServiceCall.execute(WatsonService.java:459)

如果我想通过Watson APIs Java SDK使用Token进行认证,我应该怎么做?

There is actually an example in the README of the Java SDK:有一种方法 setIamCredentials() 可以配置 Watson 服务(包括 Watson Assistant)如何处理基于令牌的访问。如果您提供 API 密钥,它可以为您管理令牌刷新,或者您传入令牌本身并需要处理刷新。

未测试,但类似于发现服务的示例并为您改编代码:

mAssistant = new Assistant("2018-02-16");
IamOptions options = new IamOptions.Builder()
  .apiKey("<iam_api_key>")
  .build();
mAssistant.setIamCredentials(options);

请注意,这是使用战略 IBM Cloud IAM (Identity and Access Management),而不是 Watson 服务令牌。该功能最近被添加到 Watson 服务中,我建议使用它。您可以使用 UI 或 bx iam 命令管理 API 密钥。

编辑:以下答案适用于您之前获得的令牌。但是,我刚刚注意到您使用 https://gateway.watsonplatform.net/conversation/api URL 调用令牌 API。如果您改为使用 https://gateway.watsonplatform.net/assistant/api 获得令牌,您发布的代码应该可以正常工作。


由于对话 -> 助理重命名,使用新名称的授权似乎存在问题。因此,一旦获得授权令牌,就可以使用 setEndPoint() 方法调用对话端点,如下所示:

mAssistant = new Assistant("2018-02-16");
Map<String, String> map = new HashMap<>();
map.put("X-Watson-Authorization-Token", "{token_string}");
mAssistant.setDefaultHeaders(map);
mAssistant.setSkipAuthentication(true);

// change here
mAssistant.setEndPoint("https://gateway.watsonplatform.net/conversation/api");

Assistant 只是 Conversation 内部的一个别名,因此您的 API 通话应该同样有效。

或者,您可以直接使用 Conversation 服务,尽管在某些时候它会消失,而只支持 Google 助理服务。

下面的代码对我来说工作正常,但我有一个问题,哪种方法更好?

方法一

通过urlhttps://gateway.watsonplatform.net/assistant/api

获取令牌
curl -X GET --user {username}:{password} "https://gateway.watsonplatform.net/authorization/api/v1/token?url=https://gateway.watsonplatform.net/assistant/api"

使用令牌

mAssistant = new Assistant("2018-02-16");
Map<String, String> map = new HashMap<>();
map.put("X-Watson-Authorization-Token", "{token_string}");
mAssistant.setDefaultHeaders(map);
mAssistant.setSkipAuthentication(true);

方法二

通过urlhttps://gateway.watsonplatform.net/conversation/api

获取令牌
curl -X GET --user {username}:{password} "https://gateway.watsonplatform.net/authorization/api/v1/token?url=https://gateway.watsonplatform.net/conversation/api"

使用令牌

mAssistant = new Assistant("2018-02-16");
Map<String, String> map = new HashMap<>();
map.put("X-Watson-Authorization-Token", "{token_string}");
mAssistant.setDefaultHeaders(map);
mAssistant.setSkipAuthentication(true);
mAssistant.setEndPoint("https://gateway.watsonplatform.net/conversation/api");