【问题标题】:Get Keycloak AccessToken in controller在控制器中获取 Keycloak AccessToken
【发布时间】:2022-11-11 01:15:33
【问题描述】:

我试图在成功登录后获取访问令牌,经过大量研究后,我找到了这篇文章,how to get Keycloak access token and store it in db for spring boot?,据说可以手动进行 Keycloak 登录,但我不知道怎么做。 cmets 中的文档链接不再起作用。

我也厌倦了想标题,但没有发送授权标题。

String authHeader = servletRequest.getHeader("Authorization"); //returns null
if (authHeader != null
        && !authHeader.isEmpty()
        && authHeader.startsWith("Bearer")) {

    String accessToken = authHeader.substring("Bearer".length()).trim();

    if (accessToken != null) {
        return new ResponseEntity(true, HttpStatus.OK);

    } else {
        return new ResponseEntity(false, HttpStatus.UNAUTHORIZED);
    }
} else {
    log.error("Invalid authorization header. ");
    return new ResponseEntity(HttpStatus.BAD_REQUEST);
}

我也尝试通过 Principal 获取它,但出现错误:

java.lang.ClassCastException:类 org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken 不能转换为类 org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken

ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder
        .currentRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
KeycloakAuthenticationToken userPrincipal = (KeycloakAuthenticationToken) request.getUserPrincipal();
SimpleKeycloakAccount userPrincipalDetails = (SimpleKeycloakAccount) userPrincipal.getDetails();
return userPrincipalDetails
        .getKeycloakSecurityContext()
        .getToken();

如果我尝试,则会显示相同的错误:

KeycloakAuthenticationToken authenticatication = (KeycloakAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();

我可以登录/注销,但我无法获取 accessToken...

@KeycloakConfiguration
@EnableWebSecurity
@Order(1)
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    private final KeycloakLogoutHandler keycloakLogoutHandler;

    public SecurityConfig(KeycloakLogoutHandler keycloakLogoutHandler) {
        this.keycloakLogoutHandler = keycloakLogoutHandler;
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider  = keycloakAuthenticationProvider();
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
       
        http.authorizeRequests()
                .antMatchers("/somepage/*").permitAll()
                .anyRequest().authenticated();

        http.oauth2Login()
                .and()
                .logout()
                .addLogoutHandler(keycloakLogoutHandler)
                .logoutSuccessUrl("/");
    }

}

有任何想法吗?

【问题讨论】:

    标签: spring-boot keycloak access-token


    【解决方案1】:

    首先,不要为 Spring 使用 Keycloak 库:it is (very) deprecated。而是使用:

    • spring-boot-starter-oauth2-resource-server 如果您的应用是 REST API。指令在this series of tutorials的第一个。
    • spring-boot-starter-oauth2-client 如果您的应用提供 UI(使用 thymeleaf 或其他)

    SecurityContextHolder.getContext().getAuthentication() 返回的 Authentication 的确切类型取决于您的应用程序是客户端还是资源服务器,并且它配置了 JWT 解码器或令牌自省,但都公开了 Bearer 访问令牌字符串。只是从那里得到它。

    如果您的应用程序是资源服务器 (REST API),您可以使用我为 spring-boot-starter-oauth2-resource-server 属性中的自动配置维护的 spring-boot 启动器之一。与之前链接的第一个教程相比,这大大简化了配置:

    <dependency>
        <groupId>com.c4-soft.springaddons</groupId>
        <artifactId>spring-addons-webmvc-jwt-resource-server</artifactId>
        <version>6.0.4</version>
    </dependency>
    
    @EnableMethodSecurity
    public static class WebSecurityConfig { }
    
    com.c4-soft.springaddons.security.issuers[0].location=https://localhost:8443/realms/master
    com.c4-soft.springaddons.security.issuers[0].authorities.claims=realm_access.roles,ressource_access.some-client.roles
    
    com.c4-soft.springaddons.security.cors[0].path=/some-api
    

    授权请求的身份验证将是JwtAuthenticationToken

    @RestController
    @RequestMapping("/demo")
    public class DemoController {
    
        @GetMapping("/access-token")
        @PreAuthorize("isAuthenticated()")
        public String getAccessToken(JwtAuthenticationToken auth) {
            return auth.getToken().getTokenValue();
        }
    }
    

    免责声明:小心你对访问令牌所做的事情以及你将它暴露给谁。如果它泄漏,它可能被用于身份盗用。

    【讨论】:

      猜你喜欢
      • 2021-05-30
      • 2013-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-20
      • 2021-08-15
      • 1970-01-01
      相关资源
      最近更新 更多