在使用 Keycloak 保护的网络应用程序中获取登录用户名

Fetch Logged In Username in a webapp secured with Keycloak

我已经使用基于 wildfly 的标准 Keycloak 适配器通过 Keycloak 保护了一个企业应用程序。我面临的问题是调用其余 Web 服务时需要知道当前登录的用户名。如何从 Keycloak 获取登录用户信息?

我尝试使用 SecurityContextWebListener 等。但是 none 能够提供所需的详细信息。

您从安全上下文中获取所有用户信息。

示例:

public class Greeter {

  @Context
  SecurityContext sc;

  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public String sayHello() {

    // this will set the user id as userName
    String userName = sc.getUserPrincipal().getName();

    if (sc.getUserPrincipal() instanceof KeycloakPrincipal) {
      KeycloakPrincipal<KeycloakSecurityContext> kp = (KeycloakPrincipal<KeycloakSecurityContext>)  sc.getUserPrincipal();

      // this is how to get the real userName (or rather the login name)
      userName = kp.getKeycloakSecurityContext().getIdToken().getPreferredUsername();
    }

    return "{ message : \"Hello " + userName + "\" }";
}

要传播安全上下文,您必须按照以下说明配置安全域: JBoss/Wildfly Adapter configuration

您还可以将网络应用 keycloak.json 文件中的 principal-attribute 属性 设置为 preferred_username

下一行需要添加standalone.xml:

<principal-attribute>preferred_username</principal-attribute>

示例:

<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
    <secure-deployment name="war-name.war">
        <realm>realm-name</realm>
        <resource>resource-name</resource>
        <public-client>true</public-client>
        <auth-server-url>https://keycloak-hostname/auth</auth-server-url>
        <ssl-required>EXTERNAL</ssl-required>
        <principal-attribute>preferred_username</principal-attribute>
    </secure-deployment>
</subsystem>

在 Keycloak 3.4.3(也可能适用于早期版本)中,我能够将用户名映射到 sub 令牌声明名称。在 Keycloak 管理界面中,这是在 Clients > [your-client] > Mappers > username 下完成的,然后在 Token Claim Name 字段中输入 sub。这具有实际更改 Keycloak 返回的 ID token 内容的优势,而不是像 中那样调整客户端。当您使用标准的 OpenID Connect 库而不是 Keycloak 提供的适配器时,这特别好。

在我的例子中,我像这样从令牌中获取首选用户名

keycloakPrincipal.getKeycloakSecurityContext().getToken();
token.getPreferredUsername();

为了工作,我必须去 keycloak 并在我的客户端模板上添加内置函数,如果没有添加首选用户名则为空。

检查内置插件、客户端模板 -> 映射器上的用户名。

之后如果成功了!