我的 Power BI 身份验证过程和 Web 请求有什么问题?

What is wrong with my Power BI Authentication process and webrequest?

最终编辑:答案已找到。这是一个依赖性问题。阅读下面的答案。

我正在开发一个程序,最终应该将数据从 SQL 服务器数据库实时推送到我们的 Power BI 报告。我目前正处于尝试从我的客户端应用程序连接到我的 Power BI 的阶段。

对于身份验证过程,我已按照以下代码示例进行操作: https://gist.github.com/dquig/a4f2f02fe3e306cebe2e 身份验证似乎工作正常。我得到了一个访问令牌(每次都是一样的,我还没有发现这是否是应该的)。编辑:我还检查了 OAuth2、powerBI API 的所有 msdn 页面(包括 Azure Active Directory 步骤)。

编辑:我刚刚注意到,如果我填写完全是胡说八道,我什至会得到一个访问令牌(为什么我以前不尝试这个...)。我每次得到的都是相同的标记。 Web 请求的响应具有 200 状态,但实体为空。

这是我的身份验证代码(我在这里省略了请求):

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.microsoft.aad.adal4j.AuthenticationContext;

public class PowerBIController {

private static final String POWER_BI_BASE_URL = "https://api.powerbi.com";
private static final String AUTH_URI = "https://login.windows.net/common/oauth2/authorize";
private static final String RESOURCE_URI = "https://analysis.windows.net/powerbi/api";
private static final boolean VALIDATE_AUTHORITY = false;

private static final String NATIVE_CLIENT_ID = "4b2f0d69-c17d-4d61-b2c0-4aeee5dfffe8";
private static final String USER_AT_TENANT = "powerBIUser@pveermanvicrea.onmicrosoft.com";
private static final String PASSWORD = "****";

private AuthenticationContext context = null;
private Client client;
private ExecutorService service = null;
private Response response;

public PowerBIController() throws Exception {
    client = ClientBuilder.newClient();
    service = Executors.newSingleThreadExecutor();
    context = new AuthenticationContext(AUTH_URI, VALIDATE_AUTHORITY, service);
    String powerBIAccessToken = getToken(RESOURCE_URI, NATIVE_CLIENT_ID, USER_AT_TENANT, PASSWORD);
}

private String getToken(String resourceUri, String nativeClientId,
        String tenant, String password) throws ExecutionException, InterruptedException{
    return context.acquireToken(
            resourceUri,
            nativeClientId,
            tenant,
            password,
            null
    ).get().getAccessToken();
}

然后是http请求: 我尝试复制粘贴整个示例(来自上面的 link),但 readEntity 不是 Response 的方法。我在这个 Read response body in JAX-RS client from a post request 上找到了以下 post。但我使用的是 javax.ws.rs 的 2.0 版。所以,这对我来说有点困惑。

public PowerBIController() throws Exception {
    client = ClientBuilder.newClient();
    service = Executors.newSingleThreadExecutor();
    context = new AuthenticationContext(AUTH_URI, VALIDATE_AUTHORITY, service);
    String powerBIAccessToken = getToken(RESOURCE_URI, NATIVE_CLIENT_ID, USER_AT_TENANT, PASSWORD);    
    post(biTarget, powerBIAccessToken);
}
private void post(WebTarget biTarget, String powerBIAccessToken) throws URISyntaxException, IOException, ExecutionException, InterruptedException {
    Response response = target
    Invocation.Builder builder = biTarget.request(MediaType.APPLICATION_JSON);
    Invocation.Builder header = builder.header("Authorization",
                                               "Bearer " +    powerBIAccessToken);
    response = header.get();
    System.out.println("header: " + header.toString());
    System.out.println("status: " + response.getStatus());
    System.out.println("body:" + response.readEntity(String.class));
}

我在 http://docs.powerbi.apiary.io/ 查过。在这里,我必须登录到我的 Office 365 帐户,然后我可以使用相同的代码来获取数据集列表。在这里我不必进行身份验证,这可能会有所不同,但是当我 运行 作为调试时,我可以清楚地看到我有一个访问令牌。 这是他们说可以正确调用 get 请求的代码。显然这行不通我也很确定目标有错别字:

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

Client client = ClientBuilder.newClient();
Response response = client.target("https://api.powerbi.com/beta/myorghttps://api.powerbi.com/beta/myorg/datasets{?defaultRetentionPolicy}")
  .request(MediaType.TEXT_PLAIN_TYPE)
  .header("undefined", "")
  .get();

System.out.println("status: " + response.getStatus());
System.out.println("headers: " + response.getHeaders());
System.out.println("body:" + response.readEntity(String.class));

我已经尝试使用 Fiddler 来查看当我 运行 时实际发生了什么。但是,Fiddler 根本没有显示 activity(即使我检查了 https 选项)。

最后,这是我对这段代码的依赖:

<dependency>
  <groupId>javax.ws.rs</groupId>
   <artifactId>javax.ws.rs-api</artifactId>
  <version>2.0</version>
</dependency>
<dependency>
  <groupId>org.jboss.resteasy</groupId>
   <artifactId>resteasy-client</artifactId>
  <version>3.0.2.Final</version>
</dependency>
<dependency>
  <groupId>com.microsoft.azure</groupId>
   <artifactId>adal4j</artifactId>
  <version>1.0.0</version>
</dependency>

我真的很期待任何帮助。如果我的问题有任何问题,请说出来。我尽我最大的努力让自己清楚并遵守这个论坛的规则,但我可能漏掉了一些东西。

非常感谢

回答:我的部分程序也使用了 azure-media 0.6.0。这包括球衣核心 1.3.1。结论:即使我认为我是从 javax.ws.rs 2.0 导入的(如果您查看类型,它甚至会说)它实际上是从 jersey 1.3.1 获取其对象定义。这不仅仅适用于 azure-media 依赖项。

所以我将 post 需要排除的依赖项和必要的最终依赖项。

<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-management</artifactId>
<version>0.7.0</version>
<exclusions>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
    </exclusion>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-json</artifactId>
    </exclusion>
</exclusions>
</dependency>
<dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-servicebus</artifactId>
<version>0.7.0</version>
<exclusions>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
    </exclusion>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-json</artifactId>
    </exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-serviceruntime</artifactId>
<version>0.6.0</version>
<exclusions>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
    </exclusion>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-json</artifactId>
    </exclusion>
</exclusions>
</dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-media</artifactId>
<version>0.6.0</version>
<exclusions>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-client</artifactId>
    </exclusion>
  <exclusion>
      <groupId>com.sun.jersey</groupId>
      <artifactId>jersey-json</artifactId>
    </exclusion>
</exclusions>
</dependency>

必要的依赖:

<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.0.2.Final</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>adal4j</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-client</artifactId>
    <version>2.19</version>
</dependency>
</dependencies>

这是打字错误吗?

Response response =client.target("https://api.powerbi.com/beta/myorghttps://api.powerbi.com/beta/myorg/datasets{?defaultRetentionPolicy}")

这是一篇完整的分步文章:https://msdn.microsoft.com/en-US/library/dn877545.aspx,对于 Power BI 身份验证,请参阅 'What you need to authenticate a Power BI client app' 部分。

所以,问题是我使用了几个 Maven 依赖项,它们在层次结构中具有部分重叠的依赖项。

例如,我包括了 Jersey 客户端 v2.1.9 以及使用 Jersey 客户端 v1.13 的 Microsoft windows azure API。

这个答案的关键点如下:当您使用 Azure SDK 和 Power BI REST API 时,您很可能会弄乱依赖关系。检查您的依赖关系层次结构以查看哪些依赖关系被多次使用。