我使用基于标准wildfly的Keycloak适配器,通过Keycloak保护了企业应用程序。 我遇到的问题是调用rest web服务时需要知道当前已登录用户的用户名。 如何从Keycloak获取已登录用户的信息?
我尝试使用SecurityContext
,WebListener
等方式,但它们都无法提供所需的详细信息。
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适配器配置中所述:
您还可以在 Web 应用程序的 keycloak.json
文件中设置 principal-attribute
属性为 preferred_username
。
SessionContext.getCallerPrincipal.getName
。 - j.con<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>
keycloakPrincipal.getKeycloakSecurityContext().getToken();
token.getPreferredUsername();
为了使工作正常进行,我必须前往Keycloak,并在我的客户端模板上添加内置内容(如果未添加,则首选用户名为空)。
检查内置内容中的用户名,客户端模板 -> 映射器。
之后就可以工作了!
sub
令牌声明名称。从Keycloak管理界面,这可以在Clients > [your-client] > Mappers > username
下完成,然后在Token Claim Name
字段中输入sub
。这样做的优点是实际上更改了由Keycloak返回的ID token
的内容,而不是像其他答案那样在客户端进行调整。当您使用标准的OpenID Connect库而不是Keycloak提供的适配器时,这非常方便。
getToken()
而不是getIdToken()
。 - devrys