为啥我使用 Azure Graph SDK 收到 400 Bad Request?

Posted

技术标签:

【中文标题】为啥我使用 Azure Graph SDK 收到 400 Bad Request?【英文标题】:Why I'm getting 400 Bad Request with Azure Graph SDK?为什么我使用 Azure Graph SDK 收到 400 Bad Request? 【发布时间】:2022-01-11 20:56:59 【问题描述】:

我正在尝试使用 Microsoft Graph SDK 验证 Azure Active Directory 中是否存在用户电子邮件,但我收到 400 Bad Request。这是尝试执行此操作的 Java/Spring 中的代码。此代码实际上是从 Microsoft 网站的 Azure 文档中提取的:

@RequestMapping( value="/hello/email", method= RequestMethod.GET )
public ResponseEntity<User> holaMundo(@PathVariable("email") String email)

    List<String> scopes = new ArrayList<String>();
    scopes.add(".default");

    String clientId = "5XXXXXX-XXXX-XXXX-XXXX-XXXX1d9c7c0";
    String clientSecret = "GXXXX~zDXXXX~N6XXXXau7mXXXXEIDmaiWXr";
    String tenantId = "39XXXX31-XXXX-XXXX-XXXX-14fXXXX4db8f";

    final ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
            .clientId(clientId)
            .clientSecret(clientSecret)
            .tenantId(tenantId)
            .build();

    final TokenCredentialAuthProvider tokenCredentialAuthProvider =
            new TokenCredentialAuthProvider(scopes, clientSecretCredential);

    final GraphServiceClient graphClient =
            GraphServiceClient
                    .builder()
                    .authenticationProvider(tokenCredentialAuthProvider)
                    .buildClient();

    User resultUser =  null;

    try 
        UserCollectionRequest ucr = graphClient.users().buildRequest().filter(email);

        UserCollectionPage ucp = ucr.get();         // Here is the error
        List<User> result = ucp.getCurrentPage();
        User u = result.get(0);
        return new ResponseEntity<>(resultUser, HttpStatus.OK);
    
    catch (IndexOutOfBoundsException e) 

    return new ResponseEntity<>(null, HttpStatus.OK);


在 UserCollectionRequest 处引发错误或异常:

UserCollectionPage ucp = ucr.get();         // Here is the error

这是错误的输出:

2021-12-06 11:51:51.626  INFO 16828 --- [onPool-worker-1] c.azure.identity.ClientSecretCredential  : Azure Identity => getToken() result for scopes [.default]: SUCCESS
2021-12-06 11:51:54.287 ERROR 16828 --- [nio-8080-exec-2] global                                   : CoreHttpProvider[sendRequestInternal] - 406Graph service exception Error code: BadRequest
2021-12-06 11:51:54.288 ERROR 16828 --- [nio-8080-exec-2] global                                   : CoreHttpProvider[sendRequestInternal] - 406Error message: Invalid filter clause
2021-12-06 11:51:54.288 ERROR 16828 --- [nio-8080-exec-2] global                                   : CoreHttpProvider[sendRequestInternal] - 406
2021-12-06 11:51:54.288 ERROR 16828 --- [nio-8080-exec-2] global                                   : CoreHttpProvider[sendRequestInternal] - 406GET https://graph.microsoft.com/v1.0/users?%24filter=fernando.rivas%40avianca.com
2021-12-06 11:51:54.289 ERROR 16828 --- [nio-8080-exec-2] global                                   : CoreHttpProvider[sendRequestInternal] - 406SdkVersion : graph-java/v5.8.0
2021-12-06 11:51:54.289 ERROR 16828 --- [nio-8080-exec-2] global                                   : CoreHttpProvider[sendRequestInternal] - 406
2021-12-06 11:51:54.289 ERROR 16828 --- [nio-8080-exec-2] global                                   : CoreHttpProvider[sendRequestInternal] - 406
2021-12-06 11:51:54.289 ERROR 16828 --- [nio-8080-exec-2] global                                   : CoreHttpProvider[sendRequestInternal] - 406400 : Bad Request
2021-12-06 11:51:54.290 ERROR 16828 --- [nio-8080-exec-2] global                                   : CoreHttpProvider[sendRequestInternal] - 406[...]
2021-12-06 11:51:54.290 ERROR 16828 --- [nio-8080-exec-2] global                                   : CoreHttpProvider[sendRequestInternal] - 406
2021-12-06 11:51:54.290 ERROR 16828 --- [nio-8080-exec-2] global                                   : CoreHttpProvider[sendRequestInternal] - 406[Some information was truncated for brevity, enable debug logging for more details]
2021-12-06 11:51:54.290 ERROR 16828 --- [nio-8080-exec-2] global                                   : Throwable detail: com.microsoft.graph.http.GraphServiceException: Error code: BadRequest
Error message: Invalid filter clause

GET https://graph.microsoft.com/v1.0/users?%24filter=fernando.rivas%40avianca.com
SdkVersion : graph-java/v5.8.0


400 : Bad Request
[...]

[Some information was truncated for brevity, enable debug logging for more details]
2021-12-06 11:51:54.297 ERROR 16828 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.microsoft.graph.http.GraphServiceException: Error code: BadRequest
Error message: Invalid filter clause

GET https://graph.microsoft.com/v1.0/users?%24filter=fernando.rivas%40avianca.com
SdkVersion : graph-java/v5.8.0


400 : Bad Request
[...]

[Some information was truncated for brevity, enable debug logging for more details]] with root cause

com.microsoft.graph.http.GraphServiceException: Error code: BadRequest
Error message: Invalid filter clause

GET https://graph.microsoft.com/v1.0/users?%24filter=fernando.rivas%40avianca.com
SdkVersion : graph-java/v5.8.0


400 : Bad Request
[...]

[Some information was truncated for brevity, enable debug logging for more details]
    at com.microsoft.graph.http.GraphServiceException.createFromResponse(GraphServiceException.java:419) ~[microsoft-graph-core-2.0.10.jar:na]
    at com.microsoft.graph.http.GraphServiceException.createFromResponse(GraphServiceException.java:378) ~[microsoft-graph-core-2.0.10.jar:na]
    at com.microsoft.graph.http.CoreHttpProvider.handleErrorResponse(CoreHttpProvider.java:511) ~[microsoft-graph-core-2.0.10.jar:na]
    at com.microsoft.graph.http.CoreHttpProvider.processResponse(CoreHttpProvider.java:440) ~[microsoft-graph-core-2.0.10.jar:na]
    at com.microsoft.graph.http.CoreHttpProvider.sendRequestInternal(CoreHttpProvider.java:406) ~[microsoft-graph-core-2.0.10.jar:na]
    at com.microsoft.graph.http.CoreHttpProvider.send(CoreHttpProvider.java:223) ~[microsoft-graph-core-2.0.10.jar:na]
    at com.microsoft.graph.http.CoreHttpProvider.send(CoreHttpProvider.java:200) ~[microsoft-graph-core-2.0.10.jar:na]
    at com.microsoft.graph.http.BaseCollectionRequest.send(BaseCollectionRequest.java:102) ~[microsoft-graph-core-2.0.10.jar:na]
    at com.microsoft.graph.http.BaseEntityCollectionRequest.get(BaseEntityCollectionRequest.java:78) ~[microsoft-graph-core-2.0.10.jar:na]
    at com.pbi336328.adverifyuser.Pbi336328.holaMundo(Pbi336328.java:56) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_301]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_301]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_301]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_301]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.8.jar:5.3.8]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1063) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.48.jar:4.0.FR]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.8.jar:5.3.8]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.48.jar:4.0.FR]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:228) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.8.jar:5.3.8]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.8.jar:5.3.8]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.8.jar:5.3.8]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.8.jar:5.3.8]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:190) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:163) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:382) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:893) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1723) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_301]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_301]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.48.jar:9.0.48]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_301]

【问题讨论】:

看起来您给过滤器的方式是问题,您可能需要传递过滤器字符串,例如 email='your-email-here',否则 API 不知道您通过哪个属性过滤或搜索。请参阅此 question 尝试按显示名称搜索。 而当你使用过滤器,搜索参数,那么额外的HTTP头ConsistencyLevel=最终必须设置,见doc 【参考方案1】:

看起来您提供过滤器的方式导致错误,您可能需要传递过滤器字符串,例如 email='your-email-here' 或 request option,否则 API 不知道您使用哪个属性正在过滤或搜索。请参阅此question,它尝试通过用户的display name 进行搜索,并且还使用了request option。 而且,当您使用 sdk 查询 MS Graph API 时,在应用 $filter、$search 时,您必须设置额外的 HTTP 标头 ConsistencyLevel = eventual 并传递 $count,按照 official doc 和 @987654323 中的此页面@

【讨论】:

您现在对过滤器有理由,但现在我收到了一个禁止错误

以上是关于为啥我使用 Azure Graph SDK 收到 400 Bad Request?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我收到异常 Azure WebJobs SDK Dashboard connection string is missing or empty 当它根本不为空时?

使用证明 jwt 使用 Graph 客户端 Sdk 添加服务主体

Microsoft Graph JavaScript SDK 3.0.0 正式发布

Microsoft Graph JavaScript SDK 3.0.0 正式发布

从Azure获取令牌以访问Microsoft Graph后无法调用函数

未从 blob 上的 azure java sdk 收到元数据字段