如何使用 KeycloakRestTemplate

HaV*_*nTe 0 spring-boot keycloak

我想实现一个简单的 Spring Boot 客户端应用程序。哪个应该访问 OAauth2 安全服务。某种代理。这个“代理服务”不应该受到保护。

我想KeycloakRestTemplate用于远程 REST 调用。

按照文档:http : //www.keycloak.org/docs/latest/securing_apps/index.html#_spring_boot_adapter

到目前为止,我包含了以下依赖项:

dependencyManagement {
  imports {
    mavenBom "org.keycloak.bom:keycloak-adapter-bom:3.4.0-FINAL"
  }
}

dependencies {
  compile('org.springframework.boot:spring-boot-starter')
  compile('org.springframework.boot:spring-boot-starter-web')
  compile('org.springframework.boot:spring-boot-starter-security')
  compile('org.keycloak:keycloak-spring-boot-starter')
  compile('org.keycloak:keycloak-spring-security-adapter')
}
Run Code Online (Sandbox Code Playgroud)

我添加了一个配置类:

@KeycloakConfiguration
public class KeycloakWebSecurityContextConfig extends 
KeycloakWebSecurityConfigurerAdapter {

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(keycloakAuthenticationProvider());
}

/**
 * Defines the session authentication strategy.
 */
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
    return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}

@Bean
public KeycloakConfigResolver KeycloakConfigResolver() {
    return new KeycloakSpringBootConfigResolver();
}

@Autowired
public KeycloakClientRequestFactory keycloakClientRequestFactory;

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public KeycloakRestTemplate keycloakRestTemplate() {
    return new KeycloakRestTemplate(keycloakClientRequestFactory);
}


@Bean
public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(
    KeycloakAuthenticationProcessingFilter filter) {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
    registrationBean.setEnabled(false);
    return registrationBean;
}

@Bean
public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(
    KeycloakPreAuthActionsFilter filter) {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
    registrationBean.setEnabled(false);
    return registrationBean;
}

@Override
protected void configure(HttpSecurity http) throws Exception
{
    super.configure(http);
    http
        .authorizeRequests()
        .anyRequest().permitAll();
}
}
Run Code Online (Sandbox Code Playgroud)

并制作了一个服务组件:

    @Autowired
private KeycloakRestTemplate template;

@Value("${person-service.url}")
private String endpoint;


@RequestMapping(value = "/person", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public Collection<Person> getPerson(){
    ResponseEntity<Person[]> entity = template.getForEntity(endpoint, Person[].class);
    return Arrays.asList(entity.getBody());
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句:“人员服务”是安全的远程服务。

调用 getPerson 方法给了我:

java.lang.IllegalStateException: Cannot set authorization header because Authentication is of type class org.springframework.security.authentication.AnonymousAuthenticationToken but class org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken is required
at org.keycloak.adapters.springsecurity.client.KeycloakClientRequestFactory.getKeycloakSecurityContext(KeycloakClientRequestFactory.java:75) ~[keycloak-spring-security-adapter-3.4.0.Final.jar:3.4.0.Final]
Run Code Online (Sandbox Code Playgroud)

我认为 spring-security 会在 KeycloakAdapter 有机会创建自己的 SecurityContext 之前创建一个 AnonymousAuthenticationToken 。

那么如何正确启动和使用 KeycloakRestTemplate 呢?

ehr*_*rdt 5

KeycloakRestTemplate 在您的微服务最初由登录用户调用时起作用,然后您可以从那里调用其他受保护的微服务。

如果您希望您的微服务发起对另一个受保护微服务的调用,您最好使用 OAuth2RestTemplate。

下面的 RestTemplate 将使用 Keycloak 服务帐户自动登录到 keycloak 并在必要时更新不记名令牌:

String url = "https://keycloakserver:8888/auth/realms/testrealm/protocol/openid-connect/token";

ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setGrantType(OAuth2Constants.CLIENT_CREDENTIALS);
resourceDetails.setAccessTokenUri(url);
resourceDetails.setClientId("your-micro-service-client-id");
resourceDetails.setClientSecret("p455word");

RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails);
Run Code Online (Sandbox Code Playgroud)