本文演示了一个 Java Servlet 应用程序,它使用 适用于 Java 的 Microsoft 身份验证库 (MSAL4J) 根据 Azure Active Directory B2C (Azure AD B2C) 来对用户进行身份验证。
下图显示了应用的拓扑结构:
该应用使用 MSAL4J 登录用户,并从 Azure AD B2C 获取 ID 令牌。 ID 令牌证明用户已通过 Azure AD B2C 租户的身份验证。
先决条件
- JDK 版本 8 或更高版本
- Maven 3
- Azure AD B2C 租户。 有关详细信息,请参阅教程:创建 Azure Active Directory B2C 租户
- 你的 Azure AD B2C 租户中的用户帐户。
建议
- 熟悉一下 Java / Jakarta Servlets。
- 熟悉一下 Linux/OSX 终端。
- 用于检查令牌的 jwt.ms。
- 用于监控网络活动和故障排除的 Fiddler。
- 关注 Microsoft Entra ID 博客,了解最新进展情况。
设置示例
以下各部分将介绍如何设置示例应用程序。
克隆或下载示例存储库
要克隆示例,请打开 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 租户
要选择租户,请按以下步骤操作:
登录到 Azure 门户。
如果你的帐户存在于多个 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)
要注册应用,请按照以下步骤操作:
导航到 Azure 门户,选择“Azure AD B2C”。
在导航窗格中选择“应用注册”,然后选择“新注册”。
在出现的“注册应用程序”页面中,输入以下应用程序注册的信息:
- 在“名称”部分中,输入一个有意义的应用名称,以便向应用用户显示,例如 。
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
- 在“名称”部分中,输入一个有意义的应用名称,以便向应用用户显示,例如 。
选择“注册”以创建应用程序。
在应用的注册页面上,找到并复制“应用程序(客户端) ID”值,以供稍后使用。 可以在应用程序的一个或多个配置文件中使用此值。
选择“保存”以保存更改。
在应用的注册页面上,选择导航窗格中的“证书和机密”,打开可生成机密和上传证书的页面。
在“客户端密码”部分中,选择“新建客户端密码”。
键入描述,例如“应用机密”。
从可用期限中选择一个:“1 年内”、“2 年内”或“永不过期”。
选择 添加 。 此时将显示生成的值。
复制并保存生成的值,以供在之后的步骤中使用。 代码的配置文件需要使用此值。 此值不会再显示,也无法通过任何其他方式获取。 因此,在导航到任何其他屏幕或窗格之前,请务必从 Azure 门户保存该值。
配置应用 (ms-identity-b2c-java-servlet-webapp-authentication) 以使用应用注册
按照以下步骤来配置应用:
注意
在以下步骤中,ClientID
与 Application ID
或 AppId
相同。
在 IDE 中打开项目。
打开 ./src/main/resources/authentication.properties 文件。
找到
aad.clientId
属性,然后用 Azure 门户中clientId
应用程序的应用程序 ID 或ms-identity-b2c-java-servlet-webapp-authentication
替换现有值。找到
aad.secret
属性,并将现有值替换为在 Azure 门户创建ms-identity-b2c-java-servlet-webapp-authentication
应用程序时保存的值。找到
aad.scopes
属性,将现有的应用程序 clientId 替换为本部分的步骤 1 中放入aad.clientId
的值。找到
aad.authority
属性,并将fabrikamb2c
的第一个实例替换为在 Azure 门户中创建ms-identity-b2c-java-servlet-webapp-authentication
应用程序的 Azure AD B2C 租户的名称。找到
aad.authority
属性,并将fabrikamb2c
的第二个实例替换为在 Azure 门户中创建ms-identity-b2c-java-servlet-webapp-authentication
应用程序的 Azure AD B2C 租户的名称。找到
aad.signInPolicy
属性,并将其替换为在 Azure 门户中创建ms-identity-b2c-java-servlet-webapp-authentication
应用程序的 Azure AD B2C 租户中创建的注册/登录用户流策略的名称。找到
aad.passwordResetPolicy
属性,并将其替换为在 Azure 门户中创建ms-identity-b2c-java-servlet-webapp-authentication
应用程序的 Azure AD B2C 租户中创建的密码重置用户流策略的名称。找到
aad.editProfilePolicy
属性,并将其替换为在 Azure 门户中创建ms-identity-b2c-java-servlet-webapp-authentication
应用程序的 Azure AD B2C 租户中创建的编辑配置文件用户流策略的名称。
生成示例
要使用 Maven 生成示例,请导航到包含示例的 pom.xml 文件的目录,然后运行以下命令:
mvn clean package
此命令会生成一个 .war 文件,它可以在各种应用服务器上运行。
运行示例
这些说明假定安装了 WebLogic 并设置了某个服务器域。
在部署到 WebLogic 之前,请按照以下步骤对示例本身进行一些配置更改,然后生成或重新生成包:
在示例中,找到在其中配置了客户端 ID、租户、重定向 URL 等的 application.properties 或 authentication.properties 文件。
在此文件中,将对
localhost:8080
或localhost:8443
的引用更改为 WebLogic 运行的 URL 和端口,而默认情况下它应该是localhost:7001
。还需要在 Azure 应用注册中进行相同的更改,即在 Azure 门户中将其设置为“身份验证”选项卡上的“重定向 URI”值。
使用以下步骤通过 Web 控制台将样本部署到 WebLogic:
通过使用 DOMAIN_NAME\bin\startWebLogic.cmd 启动 WebLogic 服务器。
在浏览器中导航到 WebLogic 网络控制台,网址为
http://localhost:7001/console
。转到 “域结构”>“部署”,选择“安装”,选择“上传文件”,然后找到使用 Maven 生成的 .war 文件。
选择“作为应用程序安装此部署”,选择“下一步”,选择“完成”,然后选择“保存”。
大部分的默认设置都可以保留,但应用程序名称除外,应将其与在示例配置或 Azure 应用程序注册中设置的重定向 URI 一致。 也就是说,如果重定向 URI 是
http://localhost:7001/msal4j-servlet-auth
,则应将应用程序命名为msal4j-servlet-auth
。返回到域结构>部署,然后启动应用程序。
在应用程序启动后,导航至
http://localhost:7001/<application-name>/
,这样就能访问应用程序了。
探索示例
按照以下步骤来探索示例:
- 注意屏幕中央显示的登录或退出状态。
- 选择角落里的上下文相关按钮。 首次运行应用时,此按钮显示“登录”。
- 在下一页中,按照说明使用所选身份供应程序的帐户登录。
- 请注意,上下文相关按钮现在显示“注销”并显示你的用户名。
- 选择“ID 令牌详细信息”以查看一些 ID 令牌的解码声明。
- 也可以选择编辑个人资料。 选择链接可编辑显示名称、居住地和职业等详细信息。
- 使用角落里的按钮注销。
- 在注销后,请导航到以下 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 | 所有可用的终结点都在 Java 类中定义,名称以 Servlet. 结尾。 |
CHANGELOG.md | 示例更改的列表。 |
CONTRIBUTING.md | 参与示例的指南。 |
许可证 | 示例的许可证。 |
ConfidentialClientApplication
如下例所示,在 ConfidentialClientApplication
文件中创建了一个 实例。 此对象有助于创建 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 文件读取的。
分步演练
以下步骤介绍了该应用的功能:
登录过程的第一步是向 Azure Active Directory B2C 租户的
/authorize
终结点发送请求。 MSAL4JConfidentialClientApplication
实例用于构建授权请求 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 重定向回调后销毁。 该状态变量可确保对/auth_redirect endpoint
的 Azure AD B2C 请求实际上是来自此应用和此会话的 Azure AD B2C 授权请求,从而防止 CSRF 攻击。 此操作是在 AADRedirectServlet.java 文件中完成的。nonce
:应用在每次令牌请求时设置到会话中的唯一变量,并在收到相应令牌后销毁。 该 nonce 会转录到 Azure AD B2C 分配的令牌中,从而确保不会发生令牌重放攻击。
Azure Active Directory B2C 会向用户显示登录提示。 如果登录尝试成功,用户的浏览器就会重定向到应用的重定向终结点。 向此终结点发出的有效请求包含授权代码。
然后,
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
:必须再次传递上一步中使用的范围。
-
如果
acquireToken
成功,则会提取令牌声明,并根据会话中存储的 nonce 来验证 nonce 声明,如下例所示:parseJWTClaimsSetAndStoreResultInSession(msalAuth, result, serializedTokenCache); validateNonce(msalAuth) processSuccessfulAuthentication(msalAuth);
如果成功验证了 nonce,就会利用
MsalAuthSession
类公开的方法将身份验证状态放入服务器端会话中,如下例所示:msalAuth.setAuthenticated(true); msalAuth.setUsername(msalAuth.getIdTokenClaims().get("name"));
详细信息
- 什么是 Azure Active Directory B2C?
- 可在 Azure Active Directory B2C 中使用的应用程序类型
- 适用于 Azure Active Directory B2C 的建议和最佳做法
- Azure AD B2C 会话
- 适用于 Java 的 Microsoft 身份验证库 (MSAL)
有关 OAuth 2.0 协议如何在此方案和其他方案中工作的详细信息,请参阅 Microsoft Entra ID 的身份验证方案。