如何在Azure AD SDK Java中按多UPN值查询用户
问题:如何批量通过UPN列表获取Azure AD用户?
我已经实现了根据单个UPN值获取匹配用户对象的代码:
@Override public AzureResponse getUsersByUPN(Map<String, String> credentials, String searchCriteria) { log.debug("in getUserByUPN() :start..."); validateToken(credentials); List<Option> requestOptions = new ArrayList<Option>(); requestOptions.add(new QueryOption("$filter", "startswith(userPrincipalName,'" + searchCriteria + "')")); List<User> users = new ArrayList<>(); AzureResponse response = new AzureResponse(); try { UserCollectionRequestBuilder usersClientBuilder = graphClient.users(); UserCollectionRequest usersRequest = usersClientBuilder.buildRequest(requestOptions); do { UserCollectionPage userCollectionPage = usersRequest.get(); users.addAll(userCollectionPage.getCurrentPage()); usersClientBuilder = userCollectionPage.getNextPage(); if (usersClientBuilder == null) { usersRequest = null; } else { usersRequest = usersClientBuilder.buildRequest(); } } while (usersRequest != null); response.setData(users); } catch (GraphServiceException e) { log.error("GraphServiceException occurred in getUserByUPN() : ", e); setErrorResponse(response, e.getResponseCode(), e.getResponseMessage()); } catch (Exception e) { log.error("Exception occurred in getUserByUPN() : ", e); setErrorResponse(response, 400, e.getMessage()); } log.debug("in getUserByUPN() :end."); return response; }
现在需要处理一个UPN列表(示例:List<String> upns = Arrays.asList("avinash@upn.com","kishore@upn.com")),获取所有对应UPN的用户对象。请问能否直接将该列表传入QueryOption的$filter参数,还是需要遍历列表逐个查询?
解答
方案1:构建批量$filter条件一次性查询
可以直接将UPN列表构建为单个$filter条件进行批量查询,无需逐个遍历。如果是精确匹配需求,建议用eq而非startswith,避免匹配到无关用户。
实现示例:
public AzureResponse getUsersByUPNs(Map<String, String> credentials, List<String> upns) { log.debug("in getUsersByUPNs() :start..."); validateToken(credentials); List<Option> requestOptions = new ArrayList<Option>(); // 构建批量filter:转义单引号避免语法错误,用or连接多个eq条件 String filter = upns.stream() .map(upn -> String.format("userPrincipalName eq '%s'", upn.replace("'", "\\'"))) .collect(Collectors.joining(" or ")); requestOptions.add(new QueryOption("$filter", filter)); List<User> users = new ArrayList<>(); AzureResponse response = new AzureResponse(); try { UserCollectionRequestBuilder usersClientBuilder = graphClient.users(); UserCollectionRequest usersRequest = usersClientBuilder.buildRequest(requestOptions); do { UserCollectionPage userCollectionPage = usersRequest.get(); users.addAll(userCollectionPage.getCurrentPage()); usersClientBuilder = userCollectionPage.getNextPage(); if (usersClientBuilder == null) { usersRequest = null; } else { usersRequest = usersClientBuilder.buildRequest(); } } while (usersRequest != null); response.setData(users); } catch (GraphServiceException e) { log.error("GraphServiceException occurred in getUsersByUPNs() : ", e); setErrorResponse(response, e.getResponseCode(), e.getResponseMessage()); } catch (Exception e) { log.error("Exception occurred in getUsersByUPNs() : ", e); setErrorResponse(response, 400, e.getMessage()); } log.debug("in getUsersByUPNs() :end."); return response; }
关键注意事项
- 特殊字符转义:必须对UPN中的单引号进行转义(
replace("'", "\\'")),否则会导致Graph API请求语法错误。 - 请求长度限制:Graph API对请求URL的长度有上限(约2000字符),如果UPN列表过长(比如超过50个),构建的filter会超出限制,返回400错误。此时需要:
- 将UPN列表分批(比如每20个一组),分别查询后合并结果;
- 或 fallback 到逐个查询的方案。
- 速率限制:批量查询性能优于多次单请求,但如果查询频率过高或单次返回数据量过大,可能触发Graph API的速率限制,需做好重试机制。
方案2:遍历列表逐个查询
如果UPN数量极少,或担心批量查询的长度/阈值问题,也可以遍历列表调用现有的getUsersByUPN方法,最后合并结果。但该方式会产生多次API请求,效率较低,不建议用于大量UPN的场景。
内容的提问来源于stack exchange,提问作者Avinash Reddy
相关产品推荐
相关产品推荐

