使用 Microsoft Graph 和仅限应用的身份验证生成 Java 应用
本教程介绍如何生成一个 Java 控制台应用,该应用使用 Microsoft Graph API 使用仅应用身份验证访问数据。 对于需要访问组织中所有用户的数据的后台服务或应用程序,仅应用身份验证是一个不错的选择。
注意
若要了解如何使用 Microsoft Graph 代表用户访问数据,请参阅此 用户 (委托) 身份验证教程。
在本教程中,你将:
提示
作为本教程的替代方法,可以下载或克隆 GitHub 存储库 ,并按照 README 中的说明注册应用程序并配置项目。
先决条件
在开始本教程之前,应在开发计算机上安装 Java SE 开发工具包 (JDK) 和 Gradle 。
还应具有具有全局管理员角色的Microsoft工作或学校帐户。 如果没有 Microsoft 365 租户,则可以通过 Microsoft 365 开发人员计划获得租户;有关详细信息,请参阅 常见问题解答。 或者,可以 注册 1 个月的免费试用版或购买 Microsoft 365 计划。
注意
本教程使用 OpenJDK 版本 17.0.2 和 Gradle 7.4.2 编写。 本指南中的步骤可能适用于其他版本,但尚未测试。
在门户中注册该应用
在本练习中,你将在 Azure Active Directory 中注册一个新应用程序,以启用 仅限应用的身份验证。 可以使用 Microsoft Entra 管理中心或使用 Microsoft Graph PowerShell SDK 注册应用程序。
注册应用程序进行仅限应用的身份验证
在本部分中,你将使用 客户端凭据流注册支持仅限应用身份验证的应用程序。
打开浏览器,导航到 Microsoft Entra 管理中心 ,并使用全局管理员帐户登录。
在左侧导航栏中选择“Microsoft Entra ID”,依次展开“标识”、“应用程序”和“应用注册”。
选择“新注册”。 输入应用程序的名称,例如
Graph App-Only Auth Tutorial
。将 “支持的帐户类型 ”设置为 “仅此组织目录中的帐户”。
保留“重定向 URI”为空。
选择“注册”。 在应用程序的 “概述 ”页上,复制 “应用程序 (客户端) ID ”和 “目录 (租户) ID ”的值并保存它们,下一步将需要这些值。
在“管理”下选择 “API 权限”。
删除“配置权限”下的默认 User.Read 权限,方法是在其行中选择省略号 (...) 并选择“删除权限”。
选择“ 添加权限”,然后选择 “Microsoft Graph”。
选择“应用程序权限”。
选择 “User.Read.All”,然后选择“ 添加权限”。
选择“ 授予管理员同意...”,然后选择“ 是 ”,为所选权限提供管理员同意。
选择“管理”下的“证书和机密”,然后选择“新建客户端密码”。
输入说明,选择持续时间,然后选择 “添加”。
复制 “值 ”列中的机密,后续步骤中将需要它。
重要
此客户端密码不会再次显示,所以请务必现在就复制它。
注意
请注意,与注册用户身份验证时的步骤不同,在本部分中,你配置了对应用注册Microsoft Graph 权限。 这是因为仅应用身份验证使用 客户端凭据流,这需要在应用注册上配置权限。 有关详细信息 ,请参阅 .default 范围 。
创建 Java 控制台应用
在本部分中,你将创建一个基本的 Java 控制台应用。
在要在其中创建项目的目录中打开命令行界面 (CLI) 。 运行以下命令以创建新的 Gradle 项目。
gradle init --dsl groovy --test-framework junit --type java-application --project-name graphapponlytutorial --package graphapponlytutorial
创建项目后,请运行以下命令以在 CLI 中运行应用,验证它是否正常工作。
./gradlew --console plain run
如果有效,应用应输出
Hello World.
。
安装依赖项
在继续操作之前,请添加稍后将使用的一些其他依赖项。
- 适用于 Java 的 Azure 标识客户端库 ,用于对用户进行身份验证并获取访问令牌。
- Microsoft适用于 Java 的 Graph SDK 调用 Microsoft Graph。
打开 ./app/build.gradle。 更新 节
dependencies
以添加这些依赖项。dependencies { // Use JUnit test framework. testImplementation 'junit:junit:4.13.2' // This dependency is used by the application. implementation 'com.google.guava:guava:33.2.1-jre' implementation 'com.azure:azure-identity:1.13.0' implementation 'com.microsoft.graph:microsoft-graph:6.13.0' }
将以下内容添加到 ./app/build.gradle 的末尾。
run { standardInput = System.in }
下次生成项目时,Gradle 将下载这些依赖项。
加载应用程序设置
在本部分中,你将向项目添加应用注册的详细信息。
在 ./app/src/main/resources 目录中创建名为 graphapponlytutorial 的新目录。
在名为 oAuth.properties 的 ./app/src/main/resources/graphapponlytutorial 目录中创建一个新文件,并在该文件中添加以下文本。
app.clientId=YOUR_CLIENT_ID_HERE app.clientSecret=YOUR_CLIENT_SECRET_HERE app.tenantId=YOUR_TENANT_ID_HERE
根据下表更新值。
设置 值 app.clientId
应用注册的客户端 ID app.tenantId
组织的租户 ID app.clientSecret
客户端密码 重要
如果使用 git 等源代码管理,则现在是从源代码管理中排除 oAuth.properties 文件的好时机,以避免无意中泄露应用 ID。
设计应用
在本部分中,你将创建一个基于控制台的简单菜单。
打开 ./app/src/main/java/graphapponlytutorial/App.java 并添加以下
import
语句。package graphapponlytutorial; import java.io.IOException; import java.util.InputMismatchException; import java.util.Properties; import java.util.Scanner; import com.microsoft.graph.models.User;
将现有的
main
函数替换为以下内容。public static void main(String[] args) { System.out.println("Java App-Only Graph Tutorial"); System.out.println(); final Properties oAuthProperties = new Properties(); try { oAuthProperties.load(App.class.getResourceAsStream("oAuth.properties")); } catch (IOException e) { System.out.println("Unable to read OAuth configuration. Make sure you have a properly formatted oAuth.properties file. See README for details."); return; } initializeGraph(oAuthProperties); Scanner input = new Scanner(System.in); int choice = -1; while (choice != 0) { System.out.println("Please choose one of the following options:"); System.out.println("0. Exit"); System.out.println("1. Display access token"); System.out.println("2. List users"); System.out.println("3. Make a Graph call"); try { choice = input.nextInt(); } catch (InputMismatchException ex) { // Skip over non-integer input } input.nextLine(); // Process user choice switch(choice) { case 0: // Exit the program System.out.println("Goodbye..."); break; case 1: // Display access token displayAccessToken(); break; case 2: // List users listUsers(); break; case 3: // Run any Graph code makeGraphCall(); break; default: System.out.println("Invalid choice"); } } input.close(); }
在文件末尾添加以下占位符方法。 你将在后面的步骤中实现它们。
private static void initializeGraph(Properties properties) { // TODO } private static void displayAccessToken() { // TODO } private static void listUsers() { // TODO } private static void makeGraphCall() { // TODO }
这将实现基本菜单,并从命令行读取用户的选择。
- 删除 ./app/src/test/java/graphapponlytutorial/AppTest.java。
添加仅限应用的身份验证
在本部分中,将向应用程序添加仅限应用的身份验证。 这是获取调用 Microsoft Graph 所需的 OAuth 访问令牌所必需的。 在此步骤中,你将 将适用于 Java 的 Azure 标识客户端库 集成到应用程序中,并为 适用于 Java 的 Microsoft Graph SDK 配置身份验证。
为 Graph 客户端配置仅限应用的身份验证
在本部分中, ClientSecretCredential
你将使用 类通过 客户端凭据流请求访问令牌。
在名为 Graph.java 的 ./app/src/main/java/graphapponlytutorial 目录中创建一个新文件,并将以下代码添加到该文件。
package graphapponlytutorial; import java.util.Properties; import com.azure.core.credential.AccessToken; import com.azure.core.credential.TokenRequestContext; import com.azure.identity.ClientSecretCredential; import com.azure.identity.ClientSecretCredentialBuilder; import com.microsoft.graph.models.UserCollectionResponse; import com.microsoft.graph.serviceclient.GraphServiceClient;
添加空 Graph 类定义。
public class Graph { }
将以下代码添加到 Graph 类。
private static Properties _properties; private static ClientSecretCredential _clientSecretCredential; private static GraphServiceClient _appClient; public static void initializeGraphForAppOnlyAuth(Properties properties) throws Exception { // Ensure properties isn't null if (properties == null) { throw new Exception("Properties cannot be null"); } _properties = properties; if (_clientSecretCredential == null) { final String clientId = _properties.getProperty("app.clientId"); final String tenantId = _properties.getProperty("app.tenantId"); final String clientSecret = _properties.getProperty("app.clientSecret"); _clientSecretCredential = new ClientSecretCredentialBuilder() .clientId(clientId) .tenantId(tenantId) .clientSecret(clientSecret) .build(); } if (_appClient == null) { _appClient = new GraphServiceClient(_clientSecretCredential, new String[] { "https://graph.microsoft.com/.default" }); } }
将 App.java 中的空
initializeGraph
函数替换为以下内容。private static void initializeGraph(Properties properties) { try { Graph.initializeGraphForAppOnlyAuth(properties); } catch (Exception e) { System.out.println("Error initializing Graph for user auth"); System.out.println(e.getMessage()); } }
此代码声明两个 ClientSecretCredential
私有属性:对象和 GraphServiceClient
对象。 函数 initializeGraphForAppOnlyAuth
创建 的新实例 ClientSecretCredential
,然后使用该实例创建 的新 GraphServiceClient
实例。 每次通过 _appClient
进行 API 调用以Microsoft Graph 时,都会使用提供的凭据来获取访问令牌。
测试 ClientSecretCredential
接下来,添加代码以从 ClientSecretCredential
获取访问令牌。
将以下函数添加到
Graph
类。public static String getAppOnlyToken() throws Exception { // Ensure credential isn't null if (_clientSecretCredential == null) { throw new Exception("Graph has not been initialized for app-only auth"); } // Request the .default scope as required by app-only auth final String[] graphScopes = new String[] {"https://graph.microsoft.com/.default"}; final TokenRequestContext context = new TokenRequestContext(); context.addScopes(graphScopes); final AccessToken token = _clientSecretCredential.getToken(context).block(); return token.getToken(); }
将 App.java 中的空
displayAccessToken
函数替换为以下内容。private static void displayAccessToken() { try { final String accessToken = Graph.getAppOnlyToken(); System.out.println("Access token: " + accessToken); } catch (Exception e) { System.out.println("Error getting access token"); System.out.println(e.getMessage()); } }
生成并运行应用。 当系统提示输入选项时,请输入
1
。 应用程序显示访问令牌。Java App-Only Graph Tutorial Please choose one of the following options: 0. Exit 1. Display access token 2. List users 3. Make a Graph call 1 App-only token: eyJ0eXAiOiJKV1QiLCJub25jZSI6IlVDTzRYOWtKYlNLVjVkRzJGenJqd2xvVUcwWS...
提示
仅出于验证和调试目的,只能) 使用 Microsoft 的联机令牌分析程序在 中https://jwt.ms解码工作或学校帐户的用户访问令牌 (。 如果在调用 Microsoft Graph 时遇到令牌错误,这很有用。 例如,验证令牌中的声明是否
scp
包含预期的 Microsoft Graph 权限范围。
列出用户
在本部分中,你将添加使用仅限应用的身份验证列出 Azure Active Directory 中的所有用户的功能。
打开 Graph.java 并将以下函数添加到 Graph 类。
public static UserCollectionResponse getUsers() throws Exception { // Ensure client isn't null if (_appClient == null) { throw new Exception("Graph has not been initialized for app-only auth"); } return _appClient.users().get(requestConfig -> { requestConfig.queryParameters.select = new String[] { "displayName", "id", "mail" }; requestConfig.queryParameters.top = 25; requestConfig.queryParameters.orderby = new String[] { "displayName" }; }); }
将 App.java 中的空
listUsers
函数替换为以下内容。private static void listUsers() { try { final UserCollectionResponse users = Graph.getUsers(); // Output each user's details for (User user: users.getValue()) { System.out.println("User: " + user.getDisplayName()); System.out.println(" ID: " + user.getId()); System.out.println(" Email: " + user.getMail()); } final Boolean moreUsersAvailable = users.getOdataNextLink() != null; System.out.println("\nMore users available? " + moreUsersAvailable); } catch (Exception e) { System.out.println("Error getting users"); System.out.println(e.getMessage()); } }
运行应用,登录并选择选项 4 以列出用户。
Please choose one of the following options: 0. Exit 1. Display access token 2. List users 3. Make a Graph call 2 User: Adele Vance ID: 05fb57bf-2653-4396-846d-2f210a91d9cf Email: AdeleV@contoso.com User: Alex Wilber ID: a36fe267-a437-4d24-b39e-7344774d606c Email: AlexW@contoso.com User: Allan Deyoung ID: 54cebbaa-2c56-47ec-b878-c8ff309746b0 Email: AllanD@contoso.com User: Bianca Pisani ID: 9a7dcbd0-72f0-48a9-a9fa-03cd46641d49 Email: NO EMAIL User: Brian Johnson (TAILSPIN) ID: a8989e40-be57-4c2e-bf0b-7cdc471e9cc4 Email: BrianJ@contoso.com ... More users available? True
代码说明
请考虑 函数中的 getUsers
代码。
访问集合
此方法返回用户的集合。 Microsoft Graph 中返回集合的大多数 API 不会在单个响应中返回所有可用结果。 相反,它们使用 分页 返回部分结果,同时为客户端提供请求下一个“页面”的方法。
默认页面大小
使用分页的 API 实现默认页面大小。 对于用户,默认值为 10。 客户端可以使用 $top 查询参数请求更多 (或更少的 ) 。 在 中 getUsers
,这是使用 top
请求配置中的 属性完成的。
注意
中 top
设置的值是上限,而不是显式数字。 API 返回指定值 内的用户 数。
获取后续页面
如果服务器上有更多可用的结果,则集合响应将包含一个 @odata.nextLink
具有 API URL 的属性,用于访问下一页。 Java 客户端库将此公开为 getOdataNextLink
集合响应对象上的方法。 如果此方法返回非 null,则有更多可用的结果。
集合排序
函数使用 orderBy
请求配置上的 属性来请求按用户的显示名称排序的结果。 这会将 $orderby 查询参数 添加到 API 调用。
可选:添加自己的代码
在本部分中,将向应用程序添加自己的 Microsoft Graph 功能。 这可能是Microsoft Graph 文档 或 Graph 资源管理器中的代码片段,也可以是你创建的代码片段。 此部分是可选的。
更新应用
打开 Graph.java 并将以下函数添加到 Graph 类。
public static void makeGraphCall() { // INSERT YOUR CODE HERE }
将 App.java 中的空
MakeGraphCallAsync
函数替换为以下内容。private static void makeGraphCall() { try { Graph.makeGraphCall(); } catch (Exception e) { System.out.println("Error making Graph call"); System.out.println(e.getMessage()); } }
选择 API
在 Microsoft Graph 中查找想要尝试的 API。 例如, 创建事件 API。 可以使用 API 文档中的示例之一,也可以在 Graph 资源管理器中自定义 API 请求并使用生成的代码片段。
配置权限
查看所选 API 的参考文档 的“权限” 部分,了解支持哪些身份验证方法。 例如,某些 API 不支持仅限应用或个人Microsoft帐户。
- 若要调用具有用户身份验证 (API(如果 API 支持用户 (委托) 身份验证) ),请参阅 用户 (委托) 身份验证 教程。
- 若要调用具有仅应用身份验证 (API(如果 API 支持) ),请在 Azure AD 管理中心中添加所需的权限范围。
添加代码
将代码复制到 makeGraphCallAsync
Graph.java 中的 函数中。 如果要从文档或 Graph 资源管理器复制代码片段,请务必将 重命名 GraphServiceClient
为 _appClient
。
恭喜!
你已完成 Java Microsoft Graph 教程。 现在,你已有一个可调用 Microsoft Graph 的工作应用,可以试验和添加新功能。
- 了解如何通过 Microsoft Graph Java SDK 使用 用户 (委托) 身份验证 。
- 访问 Microsoft Graph 概述 ,查看可以使用 Microsoft Graph 访问的所有数据。
Java 示例
你有关于此部分的问题? 如果有,请向我们提供反馈,以便我们对此部分作出改进。