使用角色和角色声明保护 Java WebLogic 应用

本文演示了一个 Java WebLogic 应用,该应用使用 OpenID Connect 登录用户并 Microsoft Entra ID 应用程序角色(应用角色) 进行授权。

此应用程序使用 Microsoft entra ID 的应用程序角色和角色声明功能实现基于角色的访问控制(RBAC)。 另一种方法是使用Microsoft Entra ID 组和组声明。 Microsoft Entra ID 组和应用程序角色不相互排斥。 可以使用它们来提供精细的访问控制。

还可以将 RBAC 与应用程序角色和角色声明配合使用,以安全地强制实施授权策略。

有关涵盖此方案和此示例的视频,请参阅 使用应用角色、安全组、范围和目录角色在应用程序中实现授权。

有关此方案和其他方案中协议的工作原理的详细信息,请参阅 身份验证与授权

此应用程序使用 MSAL for Java(MSAL4J) 登录用户并从 Microsoft Entra ID 获取 ID 令牌

此示例首先使用 MSAL for Java(MSAL4J)登录用户。 在主页上,它显示用户在其 ID 令牌中查看声明的选项。 此应用程序还允许用户查看特权管理员页面或常规用户页面,具体取决于他们分配的应用角色。 该想法是提供一个示例,说明在应用程序中,对某些功能或页面的访问仅限于用户子集,具体取决于用户所属的角色。

这种授权是使用 RBAC 实现的。 使用 RBAC,管理员向角色授予权限,而不是授予单个用户或组的权限。 然后,管理员可以将角色分配给不同的用户和组,以控制谁有权访问特定内容和功能。

此示例应用程序定义了以下两 个应用程序角色

  • PrivilegedAdmin:有权访问 “仅限 管理员”和“ 常规用户” 页面。
  • RegularUser:有权访问 “常规用户 ”页。

这些应用程序角色在 Azure 门户的应用程序注册清单中定义。 当用户登录到应用程序时,Microsoft Entra ID 会以角色成员身份向用户单独授予的每个角色发出角色声明。

可以通过Azure 门户或以编程方式使用 Microsoft Graph 和 Microsoft Azure AD PowerShell 将用户和组分配到角色。 本文介绍这两种技术。

注意

如果 https://login.microsoftonline.com/common/ 终结点用作登录用户的授权,则租户中的来宾用户不存在角色声明。 需要将用户登录到租户终结点,例如 https://login.microsoftonline.com/tenantid

先决条件

建议

设置示例

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

克隆或下载示例存储库

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

git clone https://github.com/Azure-Samples/ms-identity-msal-java-samples.git
cd 3-java-servlet-web-app/3-Authorization-II/roles

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

重要

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

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

此示例中有一个项目。 以下部分演示如何使用Azure 门户注册应用。

选择要在其中创建应用程序的Microsoft Entra ID 租户

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

  1. 登录到 Azure 门户

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

注册应用(java-servlet-webapp-roles)

首先,按照快速入门中的说明在Azure 门户中注册新应用:将应用程序注册到Microsoft 标识平台。

然后,使用以下步骤完成注册:

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

  2. 选择“新注册”。

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

    • 在“ 名称 ”部分中,输入一个有意义的应用程序名称,以便向应用的用户显示,例如 java-servlet-webapp-roles

    • “支持的帐户类型”下,选择以下选项之一:

      • 当正在生成应用程序以供租户中的用户(即单租户应用程序)使用时,才选择此组织目录中的帐户。
    • “重定向 URI”部分中,在组合框中选择“Web”,并输入以下重定向 URI: http://localhost:8080/msal4j-servlet-roles/auth/redirect

  4. 选择“注册”以创建应用程序。

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

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

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

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

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

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

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

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

定义应用程序角色

若要定义应用角色,请使用以下步骤:

  1. 仍在相同的应用注册上,选择 导航窗格中的应用角色

  2. 选择“ 创建应用角色”,然后输入以下值:

    • 对于 显示名称,请输入合适的名称 -例如 PrivilegedAdmin
    • 对于 “允许的成员类型”,请选择“ 用户”。
    • 对于 ,请输入 PrivilegedAdmin
    • 有关 说明,请输入 可查看管理员页面的 PrivilegedAdmins。
  3. 选择“ 创建应用角色”,然后输入以下值:

    • 对于 “显示名称”,请输入一个合适的名称, 例如 RegularUser
    • 对于 “允许的成员类型”,请选择“ 用户”。
    • 对于 ,请输入 RegularUser
    • 有关 说明,请输入 可以查看用户页的 RegularUsers。
  4. 选择“应用”以保存所做的更改。

将用户分配到应用程序角色

若要将用户添加到前面定义的应用角色,请遵循以下指南: 将用户和组分配到角色。


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

使用以下步骤配置应用:

注意

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

  1. 在 IDE 中打开项目。

  2. 打开 authentication.properties 文件。

  3. 找到字符串 {enter-your-tenant-id-here}。 将现有值替换为Microsoft Entra ID 租户 ID。

  4. 找到字符串{enter-your-client-id-here},并将现有值替换为从Azure 门户复制的应用程序 ID 或clientIdjava-servlet-webapp-call-graph应用程序。

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

  6. 找到该 app.roles 属性并确保值设置为 app.roles=admin PrivilegedAdmin, user RegularUser或替换特定角色的名称。

生成示例

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

mvn clean package

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

部署示例

这些说明假定你已安装 WebLogic 并设置一些服务器域。

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

  1. 在示例中,找到 配置客户端 ID、租户、重定向 URL 等的 application.propertiesauthentication.properties 文件。

  2. 在此文件中,更改对 WebLogic 运行时的 URL 和端口的引用 localhost:8080localhost:8443 默认情况下,该 URL 和端口应 localhost:7001为 。

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

使用以下步骤通过 Web 控制台将示例部署到 WebLogic:

  1. 使用 DOMAIN_NAME\bin\startWebLogic.cmd 启动 WebLogic 服务器。

  2. 在浏览器中 http://localhost:7001/console导航到 WebLogic Web 控制台。

  3. 转到“域结构>部署”,选择“安装,选择“上传文件”,然后找到使用 Maven 生成的 .war 文件。

  4. 选择“将此部署安装为应用程序”,选择“ 下一步”,选择“ 完成”,然后选择“ 保存”。

  5. 大多数默认设置都应正常,只是应将应用程序命名为与示例配置或 Azure 应用注册中设置的重定向 URI 匹配。 也就是说,如果重定向 URI 为 http://localhost:7001/msal4j-servlet-auth,则应将应用程序 msal4j-servlet-auth命名。

  6. 返回到域结构>部署,然后启动应用程序。

  7. 应用程序启动后,导航到 http://localhost:7001/<application-name>/,应该能够访问该应用程序。

探索示例

使用以下步骤浏览示例:

  1. 请注意屏幕中心显示的已登录或注销状态。
  2. 选择角落中的上下文敏感按钮。 首次运行应用时,此按钮将 读取登录
  3. 在下一页上,按照说明使用 Microsoft Entra ID 租户中的帐户登录。
  4. 在同意屏幕上,请注意请求的范围。
  5. 请注意,上下文敏感按钮现在显示 “注销 ”并显示用户名。
  6. 选择 ID 令牌详细信息 以查看某些 ID 令牌的解码声明。
  7. 选择“仅管理员”以查看/admin_only页面。 只有具有应用角色 PrivilegedAdmin 的用户才能查看此页面。 否则,会显示授权失败消息。
  8. 选择“常规用户以查看/regular_user页面。 只有具有应用角色 RegularUserPrivilegedAdmin 可以查看此页面的用户。 否则,会显示授权失败消息。
  9. 使用角落中的按钮注销。

关于代码

此示例使用 MSAL for Java(MSAL4J)登录并获取可能包含角色声明的 ID 令牌。 根据存在的角色声明,已登录的用户可以访问任何、一个或两个受保护页面, Admins Only 以及 Regular Users

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

目录

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

文件/文件夹 说明
src/main/java/com/microsoft/azuresamples/msal4j/roles/ 此目录包含定义应用的后端业务逻辑的类。
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 参与示例的指南。
许可证 示例的许可证。

在 ID 令牌中处理角色声明

令牌的角色声明包括已登录用户分配到的角色的名称,如以下示例所示:

{
  ...
  "roles": [
    "Role1",
    "Role2",]
  ...
}

ConfidentialClientApplication

ConfidentialClientApplication实例在AuthHelper.java文件中创建,如以下示例所示。 此对象有助于创建Microsoft Entra 授权 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 claim(s)
app.protect.authenticated=/token_details

逗号分隔规则集中 app.protect.roles 列出的任何路由也是对未经身份验证的经过身份验证的用户的限制,如以下示例所示。 但是,这些路由还包含应用角色成员身份的空间分隔列表:只有至少有一个相应角色的用户才能在进行身份验证后访问这些路由。

# local short names for app roles - for example, sets admin to mean PrivilegedAdmin (useful for long rule sets defined in the next key, app.protect.roles)
app.roles=admin PrivilegedAdmin, user RegularUser

# A route and its corresponding <space-separated> role(s) that can access it; the start of the next route & its role(s) is delimited by a <comma-and-space-separator>
# this says: /admins_only can be accessed by PrivilegedAdmin, /regular_user can be accessed by PrivilegedAdmin role and the RegularUser role
app.protect.roles=/admin_only admin, /regular_user admin user

作用域

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

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

有关应用程序请求的范围,请参阅 authentication.properties。 这三个范围由 MSAL 请求,默认情况下由 Microsoft Entra ID 提供。

详细信息

下一步

将 Java WebLogic 应用部署到 Azure 上的 WebLogic 虚拟机