Spring Keycloak:获取用户 ID

Posted

技术标签:

【中文标题】Spring Keycloak:获取用户 ID【英文标题】:Spring Keycloak: Get User ID 【发布时间】:2018-01-29 20:44:33 【问题描述】:

我开发了一个 Spring Boot Webservice 并使用 Keycloak 进行访问管理。 该网站将一些用户数据存储在数据库中。我尝试将这些数据与登录的用户联系起来。

目前我将用户名与数据一起存储。但我喜欢存储用户 ID 而不是用户名。我怎样才能做到这一点?

我尝试通过以下方式获取 SecurityContext:

@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public KeycloakSecurityContext getKeycloakSecurityContext() 
    return ((KeycloakPrincipal<KeycloakSecurityContext>) getRequest().getUserPrincipal()).getKeycloakSecurityContext();

但我得到一个错误:

There was an unexpected error (type=Internal Server Error, status=500).
Error creating bean with name 'scopedTarget.getKeycloakSecurityContext'
defined in com.SiteApplication: Bean instantiation via factory method
failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [org.keycloak.KeycloakSecurityContext]: Factory method
'getKeycloakSecurityContext' threw exception; nested exception is
java.lang.ClassCastException:
org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken
cannot be cast to org.keycloak.KeycloakPrincipal

这是正确的方法吗?缺什么?

谢谢!

【问题讨论】:

【参考方案1】:

我在我们的代码中做了类似的事情。

public class AuthenticationTokenProcessingFilter extends GenericFilterBean 

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException 

            if (!(request instanceof HttpServletRequest)) 
                throw new RuntimeException("Expecting a HTTP request");
            

            RefreshableKeycloakSecurityContext context = (RefreshableKeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());

            if (context == null) 
                handleNoSecurityContext(request, response, chain);
                return;
            

            AccessToken accessToken = context.getToken();
            Integer userId = Integer.parseInt(accessToken.getOtherClaims().get("user_id").toString());

            chain.doFilter(request, response);
        


在执行此操作之前,您必须将user_id 添加到由 keycloak 发布的访问令牌中。您可以通过映射器执行此操作,如下面的屏幕截图所示。

另外,不要忘记通过将@Bean 方法添加到您的应用程序类,将上面的处理过滤器添加到您的应用程序生命周期中。

@Configuration
@EnableAutoConfiguration(exclude = FallbackWebSecurityAutoConfiguration.class, SpringBootWebSecurityConfiguration.class, DataSourceAutoConfiguration.class)
@ComponentScan
@EnableAsync
public class MyServiceClass 

    public static void main(String[] args) 
        Properties properties = new Properties();
        new SpringApplicationBuilder(MyServiceClass.class)
                .properties(properties)
                .bannerMode(Banner.Mode.OFF)
                .run(args);
    


    @Bean
    public AuthenticationTokenProcessingFilter authFilter() 
        return new AuthenticationTokenProcessingFilter();
    


【讨论】:

您好,如何将其设为整数?我认为 id 是一个 UUID,它不是 int 而是 String...谢谢! 我也想要一个整数id,因为它更方便 嗨,啊!你是对的,它是一个 UUID。我们不使用 UUID。我们创建一个单独的 user_id 属性,它是一个整数。【参考方案2】:

我找到了一个比上面更简单的解决方案:

    @GetMapping
    public ResponseEntity getEndpoint(String someParam, HttpServletRequest request) 
        KeycloakAuthenticationToken principal = (KeycloakAuthenticationToken) request.getUserPrincipal();
        String userId = principal.getAccount().getKeycloakSecurityContext().getIdToken().getSubject();

        //....do something

        return new ResponseEntity(HttpStatus.OK);
    

我认为您遇到的异常是因为您尝试将getRequest().getUserPrincipal() 转换为KeycloakPrincipal&lt;KeycloakSecurityContext&gt;,而它的类型为KeycloakAuthenticationToken,所以((KeycloakAuthenticationToken) getRequest().getUserPrincipal()) 可以工作。

【讨论】:

谢谢,就是这样:final String keycloakUuid=getKeycloakSecurityContext().getToken().getSubject().intern();

以上是关于Spring Keycloak:获取用户 ID的主要内容,如果未能解决你的问题,请参考以下文章

如何从 KeyCloak 获取用户组并用 Java 打印它们

如何在 openshift 中使用 keycloak 和 spring 读取所有用户?

Spring应用程序基本身份验证通过keycloak

如何使用 Angular -> Spring Boot Oauth2 -> Keycloak 获取 keycloak 令牌

Keycloak 登录页面未显示,我改为获取 Spring Security 登录

带有 Keycloak 的 Spring Security OAuth2 - 访问用户信息