在 Azure Active Directory B2C 中使用 MSAL4J 为 Java WebSphere 应用启用登录

本文演示了一个 Java Servlet 应用程序,该应用程序使用 适用于 Java 的 Microsoft 身份验证库(MSAL4J)针对 Azure Active Directory B2C(Azure AD B2C)对用户进行身份验证。

下图显示了应用的拓扑:

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

应用使用 MSAL4J 登录用户并从 Azure AD B2C 获取 ID 令牌 。 ID 令牌证明用户已通过 Azure AD B2C 租户进行身份验证。

先决条件

建议

设置示例

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

克隆或下载示例存储库

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

git clone https://github.com/Azure-Samples/ms-identity-msal-java-samples.git
cd 3-java-servlet-web-app/1-Authentication/sign-in-b2c

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

重要

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

将示例应用程序注册到 Azure AD B2C 租户

该示例附带预注册的应用程序,用于测试目的。 若要使用自己的 Azure AD B2C 租户和应用程序,请按照以下部分中的步骤在Azure 门户中注册和配置应用程序。 否则,请继续执行运行示例的步骤

选择要在其中创建应用程序的 Azure AD B2C 租户

若要选择租户,请使用以下步骤:

  1. 登录到 Azure 门户

  2. 如果帐户存在于多个 Azure AD B2C 租户中,请选择Azure 门户角的配置文件,然后选择“切换目录”以将会话更改为所需的 Azure AD B2C 租户。

创建用户流和自定义策略

若要创建常见的用户流,例如注册、登录、配置文件编辑和密码重置,请参阅 教程:在 Azure Active Directory B2C 中创建用户流。

还应考虑 在 Azure Active Directory B2C 中创建自定义策略,但是,这超出了本教程的范围。

添加外部标识提供者

请参阅 教程:将标识提供者添加到 Azure Active Directory B2C 中的应用程序。

注册应用(ms-identity-b2c-java-servlet-webapp-authentication)

若要注册应用,请使用以下步骤:

  1. 导航到Azure 门户并选择 Azure AD B2C

  2. 在导航窗格中选择 “应用注册 ”,然后选择“ 新建注册”。

  3. 显示的“注册应用程序”页 中,输入以下应用程序注册信息:

    • 在“ 名称 ”部分中,输入一个有意义的应用程序名称,以便向应用的用户显示,例如 ms-identity-b2c-java-servlet-webapp-authentication
    • 在“支持的帐户类型”下,选择任何组织目录中的帐户和个人Microsoft帐户(例如 Skype、Xbox、Outlook.com)。
    • “重定向 URI”(可选)部分中,在组合框中选择“Web”,然后输入以下重定向 URI: http://localhost:8080/ms-identity-b2c-java-servlet-webapp-authentication/auth_redirect
  4. 选择“注册”以创建应用程序。

  5. 在应用的注册页上,查找并复制 应用程序(客户端)ID 值以供以后使用。 在应用的配置文件或文件中使用此值。

  6. 选择“保存”以保存更改。

  7. 在应用的注册页上,选择 导航窗格中的“证书和机密 ”,打开可以生成机密并上传证书的页面。

  8. 在“客户端密码”部分中,选择“新建客户端密码” 。

  9. 键入说明 - 例如应用 机密

  10. 选择可用持续时间之一: 1 年2 年内永不过期

  11. 选择 添加 。 将显示生成的值。

  12. 复制并保存生成的值,以便在后续步骤中使用。 代码的配置文件需要此值。 此值不会再次显示,不能通过任何其他方式检索该值。 因此,在导航到任何其他屏幕或窗格之前,请务必将其从Azure 门户保存。

配置应用(ms-identity-b2c-java-servlet-webapp-authentication)以使用应用注册

使用以下步骤配置应用:

注意

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

  1. 在 IDE 中打开项目。

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

  3. 找到该aad.clientId属性,并将现有值替换为应用程序 ID 或clientIdms-identity-b2c-java-servlet-webapp-authentication Azure 门户中的应用程序。

  4. 找到该属性,并将aad.secret现有值替换为在从Azure 门户创建ms-identity-b2c-java-servlet-webapp-authentication应用程序期间保存的值。

  5. 找到该属性,并将 aad.scopes 现有应用程序 clientId 替换为在本部分的步骤 1 中放置 aad.clientId 的值。

  6. 找到该aad.authority属性,并将第一个实例fabrikamb2c替换为在Azure 门户中创建ms-identity-b2c-java-servlet-webapp-authentication应用程序的 Azure AD B2C 租户的名称。

  7. 找到该aad.authority属性,并将第二个实例fabrikamb2c替换为在其中在Azure 门户中创建ms-identity-b2c-java-servlet-webapp-authentication应用程序的 Azure AD B2C 租户的名称。

  8. 找到该aad.signInPolicy属性,并将其替换为在 azure AD B2C 租户中创建的注册/登录用户流策略的名称,在该租户ms-identity-b2c-java-servlet-webapp-authentication中创建应用程序Azure 门户。

  9. 找到该aad.passwordResetPolicy属性,并将其替换为在 azure AD B2C 租户ms-identity-b2c-java-servlet-webapp-authentication中创建的应用程序在Azure 门户中创建的应用程序的密码重置用户流策略的名称。

  10. 找到该aad.editProfilePolicy属性,并将其替换为在 azure AD B2C 租户中创建的编辑配置文件用户流策略的名称,在该租户ms-identity-b2c-java-servlet-webapp-authentication中创建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. 在下一页上,按照说明使用所选标识提供者的帐户登录。
  4. 请注意,上下文敏感按钮现在显示 “注销 ”并显示用户名。
  5. 选择 ID 令牌详细信息 以查看某些 ID 令牌的解码声明。
  6. 还可以选择编辑配置文件。 选择链接可编辑详细信息,例如显示名称、居住地和职业。
  7. 使用角落中的按钮注销。
  8. 注销后,导航到令牌详细信息页的以下 URL: http://localhost:8080/ms-identity-b2c-java-servlet-webapp-authentication/auth_token_details 在这里,可以观察应用如何显示 401: unauthorized 错误而不是 ID 令牌声明。

关于代码

此示例演示如何使用 MSAL4J 将用户登录到 Azure AD B2C 租户。

目录

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

文件/文件夹 说明
AuthHelper.java 用于身份验证的帮助程序函数。
Config.java 在启动时运行,并配置属性读取器和记录器。
authentication.properties Microsoft Entra ID 和程序配置。
AuthenticationFilter.java 将未经身份验证的请求重定向到受保护的资源到 401 页。
MsalAuthSession 使用 .HttpSession 将所有与 MSAL 相关的会话属性存储在会话属性中。
____Servlet.java 所有可用的终结点在以 ____Servlet.java 结尾.java类中定义。
CHANGELOG.md 示例更改列表。
CONTRIBUTING.md 参与示例的指南。
许可证 示例的许可证。

ConfidentialClientApplication

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

IClientSecret secret = ClientCredentialFactory.createFromSecret(SECRET);
confClientInstance = ConfidentialClientApplication
                     .builder(CLIENT_ID, secret)
                     .b2cAuthority(AUTHORITY + policy)
                     .build();

以下参数用于实例化:

  • 应用的客户端 ID。
  • 客户端机密,这是机密客户端应用程序的要求。
  • Azure AD B2C 颁发机构与相应的 UserFlowPolicy 注册、登录、配置文件编辑或密码重置连接。

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

分步演练

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

  1. 登录过程的第一步是向 Azure Active Directory B2C 租户的终结点发送请求 /authorize 。 MSAL4J ConfidentialClientApplication 实例用于构造授权请求 URL,应用将浏览器重定向到此 URL,如以下示例所示:

    final ConfidentialClientApplication client = getConfidentialClientInstance(policy);
    final AuthorizationRequestUrlParameters parameters = AuthorizationRequestUrlParameters
        .builder(REDIRECT_URI, Collections.singleton(SCOPES)).responseMode(ResponseMode.QUERY)
        .prompt(Prompt.SELECT_ACCOUNT).state(state).nonce(nonce).build();
    
    final String redirectUrl = client.getAuthorizationRequestUrl(parameters).toString();
    Config.logger.log(Level.INFO, "Redirecting user to {0}", redirectUrl);
    resp.setStatus(302);
    resp.sendRedirect(redirectUrl);
    

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

    • AuthorizationRequestUrlParameters:必须设置的参数才能生成 AuthorizationRequestUrl。

    • REDIRECT_URI:收集用户凭据后,Azure AD B2C 会重定向浏览器以及身份验证代码。

    • SCOPES范围 是应用程序请求的权限。

      通常,这三个范围 openid profile offline_access 足以接收 ID 令牌响应。 但是,MSAL4J 要求来自 Azure AD B2C 的所有响应也包含访问令牌。

      为了使 Azure AD B2C 分配访问令牌和 ID 令牌,请求必须包含额外的资源范围。 由于此应用实际上不需要外部资源范围,因此它将自己的客户端 ID 添加为第四个范围,以便接收访问令牌。

      可以在 authentication.properties 文件中找到应用请求的范围的完整列表。

    • ResponseMode.QUERY:Azure AD B2C 可以将响应作为 HTTP POST 请求中的表单参数或 HTTP GET 请求中的查询字符串参数返回。

    • Prompt.SELECT_ACCOUNT:Azure AD B2C 应要求用户选择要对其进行身份验证的帐户。

    • state:应用在每个令牌请求上设置的唯一变量,并在收到相应的 Azure AD B2C 重定向回调后销毁。 状态变量可确保从来自此应用和此会话的 Azure AD B2C 授权请求实际发出 Azure AD B2C 请求 /auth_redirect endpoint ,从而防止 CSRF 攻击。 此操作在 AADRedirectServlet.java 文件中完成。

    • nonce:应用在每个令牌请求的会话中设置的唯一变量,并在收到相应的令牌后销毁。 此 nonce 将转录为分配了 Azure AD B2C 的结果令牌,从而确保没有发生令牌重播攻击。

  2. Azure Active Directory B2C 会显示用户登录提示。 如果登录尝试成功,则用户的浏览器将重定向到应用的重定向终结点。 对此终结点的有效请求包含 授权代码

  3. 然后,该 ConfidentialClientApplication 实例将此授权代码交换为 Azure Active Directory B2C 中的 ID 令牌和访问令牌,如以下示例所示:

    final AuthorizationCodeParameters authParams = AuthorizationCodeParameters
                        .builder(authCode, new URI(REDIRECT_URI))
                        .scopes(Collections.singleton(SCOPES)).build();
    
    final ConfidentialClientApplication client = AuthHelper
            .getConfidentialClientInstance(policy);
    final Future<IAuthenticationResult> future = client.acquireToken(authParams);
    final IAuthenticationResult result = future.get();
    

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

    • AuthorizationCodeParameters:必须设置的参数,才能交换 ID 和/或访问令牌的授权代码。
    • authCode:在重定向终结点收到的授权代码。
    • REDIRECT_URI:上一步中使用的重定向 URI 必须再次传递。
    • SCOPES:上一步中使用的范围必须再次传递。
  4. 如果 acquireToken 成功,则会提取令牌声明,并针对会话中存储的 nonce 验证 nonce 声明,如以下示例所示:

    parseJWTClaimsSetAndStoreResultInSession(msalAuth, result, serializedTokenCache);
    validateNonce(msalAuth)
    processSuccessfulAuthentication(msalAuth);
    
  5. 如果成功验证 nonce,身份验证状态将置于服务器端会话中,并利用类公开 MsalAuthSession 的方法,如以下示例所示:

    msalAuth.setAuthenticated(true);
    msalAuth.setUsername(msalAuth.getIdTokenClaims().get("name"));
    

详细信息

有关 OAuth 2.0 协议在此方案中的工作方式和其他方案的详细信息,请参阅 Microsoft Entra ID 的身份验证方案。

下一步

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