我目前正在将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授予对相应表的访问权限
此外,我还创建了以下代码
- 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>
- 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
- Web应用程序将未经身份验证的用户正确地转发给Microsoft,并且必要的数据也作为令牌转发给应用程序。
这里有人能帮我澄清一下我做错了什么吗?
我的猜测是配置中的Application.yaml文件未正确解析,并且OAuth2握手中未发送访问Dynamics的范围。这意味着用户未获得Dynamics客户端的授权。这也可以解释授权的客户端不存在。但是,我不知道配置中的错误
1条答案
按热度按时间csga3l581#
经过长时间的研究和尝试,我现在找到了解决办法。
是适合该配置的解决方案