azure 使用Rest API从Sping Boot 访问Microsoft Dataverse

gblwokeq  于 2023-01-27  发布在  其他
关注(0)|答案(1)|浏览(174)

我目前正在将Sping Boot 应用程序与Microsoft Dataverse连接。
存在以下要求

  • DataVerse表中的CRUD操作
  • 用户通过Microsoft帐户使用OAuth2登录Spring应用程序。

附件是说明此Sequence diagram的序列图。不幸的是,我在最终访问dataverse表时遇到401未授权错误。
到目前为止,我已经完成了以下工作
1.已在Azure中输入Web应用程序“应用程序注册”。App Registration
1.在Azure中生成客户端ID和客户端密码“App-Registration Client Secrect & ID
1.在Azure“应用程序注册”中设置Dynamics CRM和Microsoft Graph的API权限。API Access rights
1.在Power Apps Admin区域输入应用程序用户,并通过角色App User授予对相应表的访问权限
此外,我还创建了以下代码

  1. Maven中的依赖关系
<dependency>
            <groupId>com.azure.spring</groupId>
            <artifactId>spring-cloud-azure-starter-active-directory</artifactId>
        </dependency>
        <dependency>
            <groupId>com.azure.spring</groupId>
            <artifactId>azure-spring-boot-starter-active-directory</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-reactive-httpclient</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-client</artifactId>
        </dependency>
        <dependency>
  1. application.yaml
spring.cloud.azure.active-directory:
        enabled: true
        profile.tenant-id: xxxx-xxxx-xxxx-xxxx-xxxx
        credential:
          client-id: xxxxxx-xxxx-xxxx-xxxx-xxxxx
          client-secret: xxxxxxxxxxxxxxxxxxx
        application-type: web-application
        authorization-clients:                
          graph:
            authorizationGrantType: client-credentials
            scopes:
              https://graph.microsoft.com/User.Read
          dynamics:
            authorizationGrantType: client-credentials            
            scopes:
              https://xxxxxxx.crm4.dynamics.com/.default

1.休息服务

import static org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClient.RequestHeadersUriSpec;
import org.springframework.web.reactive.function.client.WebClient.ResponseSpec;

import reactor.netty.http.client.HttpClient;
import reactor.netty.transport.logging.AdvancedByteBufFormat;

@RestController
public class DataverseRestController {

    @Autowired
    private WebClient webClient;
    @Autowired
    private OAuth2AuthorizedClientService manager;

    @GetMapping("/graph")
    @ResponseBody
    public String produkte(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient client) {
        if (null == client) {
            return "Get response failed.";
        }

        RequestHeadersUriSpec<?> requestHeadersUriSpec = webClient.get();
        ResponseSpec response = requestHeadersUriSpec
                .uri("https://xxxxxxxx.crm4.dynamics.com/api/data/v9.2/cr2a0_xxxxxxxxx")
                .attributes(oauth2AuthorizedClient(client)).retrieve();
        String body = response.bodyToMono(String.class).block();
        return "Get response " + (null != body ? "successfully" : "failed");
    }

}

1.网络客户端配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;

import reactor.netty.http.client.HttpClient;
import reactor.netty.transport.logging.AdvancedByteBufFormat;

@Configuration
public class WebClientConfig {

    @Bean
    public WebClient webClient(OAuth2AuthorizedClientManager oAuth2AuthorizedClientManager) {
        ServletOAuth2AuthorizedClientExchangeFilterFunction function = new ServletOAuth2AuthorizedClientExchangeFilterFunction(
                oAuth2AuthorizedClientManager);
        HttpClient httpClient = HttpClient.create().wiretap("reactor.netty.http.client.HttpClient",
                io.netty.handler.logging.LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL);
        return WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient)).apply(function.oauth2Configuration()).build();
    }
}

我可以提出以下意见
1.奇怪的是,如果我以标准用户身份登录(该用户可以访问该表),却无法通过Rest API调用该表(401).如果我以管理员身份正常登录,我也不能然而,如果我进入环境中的Power Platform管理中心并经由链接调用那里的环境URL,尽管我已经通过了管理员身份验证,但我必须再次登录。之后,我还可以使用相同的URL从浏览器调用Dataverse中表的数据。Link where I logged in an then the tables are shown
1.调用rest接口时,我无法指定在application. yaml中配置的授权客户端。@RegisteredOAuth2AuthorizedClient和@RegisteredOAuth2AuthorizedClient(“azure”)工作正常。@RegisteredOAuth2AuthorizedClient(“dynamics”)不工作。此处为null

  1. Web应用程序将未经身份验证的用户正确地转发给Microsoft,并且必要的数据也作为令牌转发给应用程序。
    这里有人能帮我澄清一下我做错了什么吗?
    我的猜测是配置中的Application.yaml文件未正确解析,并且OAuth2握手中未发送访问Dynamics的范围。这意味着用户未获得Dynamics客户端的授权。这也可以解释授权的客户端不存在。但是,我不知道配置中的错误
csga3l58

csga3l581#

经过长时间的研究和尝试,我现在找到了解决办法。

spring.cloud.azure.active-directory:
    enabled: true
    profile.tenant-id: xxxx-xxxx-xxxx-xxxx-xxxx
    credential:
      client-id: xxxxxx-xxxx-xxxx-xxxx-xxxxx
      client-secret: xxxxxxxxxxxxxxxxxxx
    application-type: web-application
    authorization-clients:                
      **azure**:
        authorizationGrantType: **authorization_code**           
        scopes:
          https://xxxxxxx.crm4.dynamics.com/.default

是适合该配置的解决方案

相关问题