启用 Java WebSphere 应用以登录用户并访问 Microsoft Graph

本文演示了一个 Java WebSphere 应用,用于登录用户并获取用于调用 Microsoft Graph 的访问令牌。 它使用适用于 JavaMicrosoft 身份验证库 (MSAL)。

下图显示了应用的拓扑:

显示应用的拓扑的关系图。

客户端应用使用 MSAL for Java(MSAL4J)登录用户并从 Microsoft Entra ID 获取 Microsoft Graph 的访问令牌 访问令牌证明用户有权访问作用域中定义的 Microsoft Graph API 终结点。

先决条件

  • Java 8 或更高版本
  • Maven 3
  • Microsoft Entra ID 租户。 有关详细信息,请参阅 如何获取 Microsoft Entra ID 租户
  • 如果只想在组织目录中使用帐户(即单租户模式),则属于你自己的 Microsoft Entra ID 租户中的用户帐户。 如果尚未在租户中创建用户帐户,则应在继续操作之前执行此操作。 有关详细信息,请参阅 如何创建、邀请和删除用户
  • 如果要在任何组织目录中(即多租户模式)中使用帐户,则任何组织的 Microsoft Entra ID 租户中的用户帐户。 必须修改此示例才能使用个人 Microsoft 帐户。 如果尚未在租户中创建用户帐户,则应在继续操作之前执行此操作。 有关详细信息,请参阅 如何创建、邀请和删除用户
  • 如果想要使用个人 Microsoft 帐户,例如 Xbox、Hotmail、Live 等个人 Microsoft 帐户。

建议

设置示例

以下部分演示如何设置示例应用程序。

克隆或下载示例存储库

若要克隆示例,请打开 Bash 窗口并使用以下命令:

git clone https://github.com/Azure-Samples/ms-identity-java-servlet-webapp-authentication.git
cd 2-Authorization-I/call-graph

或者,导航到 ms-identity-java-servlet-webapp-authentication 存储库,然后将其下载为 .zip 文件并将其提取到硬盘驱动器。

重要

若要避免 Windows 上的文件路径长度限制,请将存储库克隆或提取到硬盘驱动器根附近的目录中。

向 Microsoft Entra ID 租户注册示例应用程序

此示例中有一个项目。 若要在Azure 门户上注册应用,可以按照手动配置步骤或使用 PowerShell 脚本。 该脚本执行以下任务:

  • 创建 Microsoft Entra ID 应用程序和相关对象,例如密码、权限和依赖项。
  • 修改项目配置文件。
  • 默认情况下,设置仅适用于组织目录中的帐户的应用程序。

使用以下步骤运行 PowerShell 脚本:

  1. 在 Windows 上,打开 PowerShell 并导航到克隆目录的根目录。

  2. 使用以下命令设置 PowerShell 的执行策略:

    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process -Force
    
  3. 使用以下命令运行配置脚本:

    cd .\AppCreationScripts\
    .\Configure.ps1
    

    注意

    应用创建脚本介绍了运行脚本的其他方法。 这些脚本还提供了自动化应用程序注册、配置和删除指南,有助于 CI/CD 方案。

配置应用(java-servlet-webapp-call-graph)以使用应用注册

使用以下步骤配置应用:

注意

在以下步骤中, ClientIDApplication IDAppId相同。

  1. 在 IDE 中打开项目。

  2. 打开 ./src/main/resources/authentication.properties 文件。

  3. 找到字符串 {enter-your-tenant-id-here}。 将现有值替换为以下值之一:

    • 如果你将此应用注册到此组织目录中的 “帐户 ”选项,则 Microsoft Entra ID 租户 ID。
    • 如果将应用注册到任何组织目录选项中的“帐户”,则为该单词organizations
    • 如果将应用注册到任何组织目录和个人 Microsoft 帐户选项中的帐户,则为该单词common
    • 如果将应用注册到个人 Microsoft 帐户选项,则为该单词consumers
  4. 找到字符串{enter-your-client-id-here},并将现有值替换为从Azure 门户复制的应用程序 ID 或clientIdjava-servlet-webapp-call-graph应用程序。

  5. 找到字符串{enter-your-client-secret-here},并将现有值替换为在创建java-servlet-webapp-call-graph应用期间保存的值(在Azure 门户中)。

生成示例

若要使用 Maven 生成示例,请导航到包含 示例pom.xml 文件的目录,然后运行以下命令:

mvn clean package

此命令生成可在 各种应用程序服务器上运行的 .war 文件。

运行示例

这些说明假定你已安装 WebSphere 并设置服务器。 可以在 Azure 虚拟机上部署 WebSphere 应用程序服务器(传统)群集中的指南进行基本服务器设置。

在部署到 WebSphere 之前,请使用以下步骤在示例本身中进行一些配置更改,然后生成或重新生成包:

  1. 导航到应用的 authentication.properties 文件,并将要使用的服务器 URL 和端口号的值 app.homePage 更改为要使用的端口号,如以下示例所示:

    # app.homePage is by default set to dev server address and app context path on the server
    # for apps deployed to azure, use https://your-sub-domain.azurewebsites.net
    app.homePage=https://<server-url>:<port-number>/msal4j-servlet-auth/
    
  2. 保存此文件后,使用以下命令重新生成应用:

    mvn clean package
    
  3. 代码生成完成后,将 .war 文件复制到目标服务器的文件系统。

还需要在 Azure 应用注册中进行更改,在Azure 门户中将其设置为“身份验证”选项卡上的“重定向 URI”值

  1. 导航到面向开发人员的 Microsoft 标识平台应用注册页

  2. 使用搜索框搜索应用注册 ,例如 java-servlet-webapp-authentication

  3. 通过选择应用名称打开应用注册。

  4. 从菜单中选择“身份验证”。

  5. “Web - 重定向 URI”部分中,选择“添加 URI”。

  6. 填写应用的 URI,追加 /auth/redirect - 例如 https://<server-url>:<port-number>/auth/redirect

  7. 选择“保存”。

使用以下步骤使用 WebSphere 的集成解决方案控制台部署示例:

  1. “应用程序”选项卡上,选择“新建应用程序,然后选择“新建企业应用程序”。

  2. 选择生成的 .war 文件,然后选择“下一步,直到到达 Web 模块安装步骤的映射上下文根。 其他默认设置应正常。

  3. 对于上下文根,请将它设置为与在示例配置/Azure 应用注册中设置的“重定向 URI”中的端口号之后的值相同。 也就是说,如果重定向 URI 为 http://<server-url>:9080/msal4j-servlet-auth/,则上下文根应为 msal4j-servlet-auth

  4. 选择“完成”。

  5. 应用程序安装完成后,转到“应用程序”选项卡的“WebSphere 企业应用程序”部分。

  6. 从应用程序列表中选择安装的 .war 文件,然后选择“开始进行部署。

  7. 部署完成后,导航到 http://<server-url>:9080/{whatever you set as the context root} 并应能够看到应用程序。

探索示例

使用以下步骤浏览示例:

  1. 请注意屏幕中心显示的已登录或注销状态。
  2. 选择角落中的上下文敏感按钮。 首次运行应用时,此按钮将 读取登录
  3. 在下一页上,按照说明使用 Microsoft Entra ID 租户中的帐户登录。
  4. 在同意屏幕上,请注意请求的范围。
  5. 请注意,上下文敏感按钮现在显示 “注销 ”并显示用户名。
  6. 选择 ID 令牌详细信息 以查看某些 ID 令牌的解码声明。
  7. 选择 Call Graph 以调用 Microsoft Graph 的 /me 终结点 ,并查看获取的用户详细信息的选择。
  8. 使用角落中的按钮注销。

关于代码

此示例使用 MSAL for Java (MSAL4J) 登录并获取 Microsoft Graph API 的令牌。 它使用 Microsoft Graph SDK for Java 从 Graph 获取数据。 必须使用 Maven 将这些库添加到项目中。

如果要副本 (replica)采样的行为,可以复制 src/main/java/com/microsoft/azuresamples/msal4j 文件夹中的 pom.xml文件和 authservlet 文件夹的内容。 还需要 authentication.properties 文件。 这些类和文件包含可在各种应用程序中使用的通用代码。 也可以复制示例的其余部分,但会专门生成其他类和文件来解决此示例的目标。

目录

下表显示了示例项目文件夹的内容:

文件/文件夹 说明
AppCreationScripts/ 用于自动配置 Microsoft Entra ID 应用注册的脚本。
src/main/java/com/microsoft/azuresamples/msal4j/callgraphwebapp/ 此目录包含定义应用的后端业务逻辑的类。
src/main/java/com/microsoft/azuresamples/msal4j/authservlets/ 此目录包含用于登录和注销终结点的类。
____Servlet.java 所有可用的终结点都在以 ____Servlet.java 结尾的.java类中定义。
src/main/java/com/microsoft/azuresamples/msal4j/helpers/ 用于身份验证的帮助程序类。
AuthenticationFilter.java 将未经身份验证的请求重定向到受保护的终结点到 401 页。
src/main/resources/authentication.properties Microsoft Entra ID 和程序配置。
src/main/webapp/ 此目录包含 UI - JSP 模板
CHANGELOG.md 示例更改列表。
CONTRIBUTING.md 参与示例的指南。
LICEN标准版 示例的许可证。

ConfidentialClientApplication

ConfidentialClientApplication实例在AuthHelper.java文件中创建,如以下示例所示。 此对象有助于创建 Microsoft Entra ID 授权 URL,并有助于交换访问令牌的身份验证令牌。

// getConfidentialClientInstance method
IClientSecret secret = ClientCredentialFactory.createFromSecret(SECRET);
confClientInstance = ConfidentialClientApplication
                     .builder(CLIENT_ID, secret)
                     .authority(AUTHORITY)
                     .build();

以下参数用于实例化:

  • 应用的客户端 ID。
  • 客户端机密,这是机密客户端应用程序的要求。
  • Microsoft Entra ID 颁发机构,其中包括你的 Microsoft Entra 租户 ID。

在此示例中,使用 Config.java 文件中的属性读取器authentication.properties 文件中读取这些值。

分步演练

以下步骤提供应用的功能的演练:

  1. 登录过程的第一步是向 Microsoft Entra ID 租户的终结点发送请求 /authorize 。 MSAL4J ConfidentialClientApplication 实例用于构造授权请求 URL。 应用将浏览器重定向到此 URL,这是用户登录的位置。

    final ConfidentialClientApplication client = getConfidentialClientInstance();
    AuthorizationRequestUrlParameters parameters = AuthorizationRequestUrlParameters.builder(Config.REDIRECT_URI, Collections.singleton(Config.SCOPES))
            .responseMode(ResponseMode.QUERY).prompt(Prompt.SELECT_ACCOUNT).state(state).nonce(nonce).build();
    
    final String authorizeUrl = client.getAuthorizationRequestUrl(parameters).toString();
    contextAdapter.redirectUser(authorizeUrl);
    

    以下列表描述了此代码的功能:

    • AuthorizationRequestUrlParameters:必须设置的参数才能生成 AuthorizationRequestUrl。
    • REDIRECT_URI:在收集用户凭据后,Microsoft Entra ID 会重定向浏览器以及身份验证代码。 它必须与Azure 门户中的 Microsoft Entra ID 应用注册中的重定向 URI 匹配
    • SCOPES范围 是应用程序请求的权限。
      • 通常,这三个范围 openid profile offline_access 足以接收 ID 令牌响应。
      • 可以在 authentication.properties 文件中找到应用请求的范围的完整列表。 可以添加更多范围,例如 User.Read 等。
  2. Microsoft Entra ID 将会向用户显示登录提示。 如果登录尝试成功,则用户的浏览器将重定向到应用的重定向终结点。 对此终结点的有效请求包含 授权代码

  3. 然后,该 ConfidentialClientApplication 实例将此授权代码交换为来自 Microsoft Entra ID 的 ID 令牌和访问令牌。

    // First, validate the state, then parse any error codes in response, then extract the authCode. Then:
    // build the auth code params:
    final AuthorizationCodeParameters authParams = AuthorizationCodeParameters
            .builder(authCode, new URI(Config.REDIRECT_URI)).scopes(Collections.singleton(Config.SCOPES)).build();
    
    // Get a client instance and leverage it to acquire the token:
    final ConfidentialClientApplication client = AuthHelper.getConfidentialClientInstance();
    final IAuthenticationResult result = client.acquireToken(authParams).get();
    

    以下列表描述了此代码的功能:

    • AuthorizationCodeParameters:必须设置的参数,才能交换 ID 和/或访问令牌的授权代码。
    • authCode:在重定向终结点收到的授权代码。
    • REDIRECT_URI:上一步中使用的重定向 URI 必须再次传递。
    • SCOPES:上一步中使用的范围必须再次传递。
  4. 如果 acquireToken 成功,则提取令牌声明。 如果 nonce 检查通过,则结果将置于 context -- 实例IdentityContextData中,并保存到会话中。 然后,应用程序可以通过需要访问会话的实例IdentityContextAdapterServlet来实例IdentityContextData化会话,如以下代码所示:

    // parse IdToken claims from the IAuthenticationResult:
    // (the next step - validateNonce - requires parsed claims)
    context.setIdTokenClaims(result.idToken());
    
    // if nonce is invalid, stop immediately! this could be a token replay!
    // if validation fails, throws exception and cancels auth:
    validateNonce(context);
    
    // set user to authenticated:
    context.setAuthResult(result, client.tokenCache().serialize());
    

保护路由

有关示例应用如何筛选路由访问权限的信息,请参阅 AuthenticationFilter.java。 在 authentication.properties 文件中,该 app.protect.authenticated 属性包含仅经过身份验证的用户可以访问的逗号分隔路由,如以下示例所示:

# for example, /token_details requires any user to be signed in and does not require special roles or groups claim(s)
app.protect.authenticated=/token_details, /call_graph

调用图

当用户导航到 /call_graph时,应用程序将从 Java Graph SDK 创建一个实例 IGraphServiceClient ,并传递已登录用户的访问令牌。 Graph 客户端在其请求的标头中 Authorization 放置访问令牌。 然后,应用要求 Graph 客户端调用 /me 终结点,以生成当前已登录用户的详细信息。

以下代码是应用程序开发人员为访问 /me 终结点而编写的全部代码,前提是它们已具有具有作用域的 User.Read Graph 服务的有效访问令牌。

//CallGraphServlet.java
User user = GraphHelper.getGraphClient(contextAdapter).me().buildRequest().get();

作用域

范围告知 Microsoft Entra ID 应用程序正在请求的访问级别。

根据请求的范围,Microsoft Entra ID 在登录时向用户显示同意对话。 如果用户同意一个或多个范围并获取令牌,则 scopes-consented-to 编码为结果 access_token

有关应用程序请求的范围,请参阅 authentication.properties。 默认情况下,应用程序将范围值设置为 User.Read。 此特定的 Microsoft Graph API 范围用于访问当前登录用户的信息。 用于访问此信息的图形终结点为 https://graph.microsoft.com/v1.0/me。 对此终结点发出的任何有效请求都必须包含access_token标头中的Authorization作用域User.Read

详细信息

下一步

将 Java WebSphere 应用部署到 Azure 上的传统 WebSphere 虚拟机