如何使用KeycloakRestTemplate

时间:2017-11-15 09:03:53

标签: 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')
}

我添加了一个Config类:

@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();
}
}

并制作了服务组件:

    @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());
}

BTW:“人员服务”是安全的远程服务。

调用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]

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

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

2 个答案:

答案 0 :(得分:0)

问题可能是您(您的客户端)未对Keycloak进行身份验证,因此缺少Keycloak令牌。

如果您未登录Keycloak,则应使用Spring中的简单Rest模板,而不是Keycloak Rest Template。

import org.springframework.web.client.RestTemplate

...

RestTemplate rt = new RestTemplate();
rt.postForObject(uri, data ,String.class);

答案 1 :(得分:0)

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

如果您希望微服务向另一个受保护的微服务发起呼叫,那么最好使用OAuth2RestTemplate。

下面的RestTemplate将使用Keycloak服务帐户自动登录到keycloak,并在必要时续订承载令牌:

$('#divAddDocument').on('change', 'input[id*="addDocCheckbox_"]', function(e) {
  var _index = this.id.split('_')[1];
  _docUpload.DmsDocumentsList[_index].IsGridItemSelected = true;

  if (_docUpload.IsCorrespondence) {
    $('input[id*="addDocCheckbox_"]').each(function() {
      if (checkboxId != this.id) {
        this.disabled = true;
        this.checked = false;
        var _counter = this.id.split('_')[1];
        _docUpload.DmsDocumentsList[_counter].IsGridItemSelected = false;
      }
    });
  }
});