Keycloak弹簧安全客户端凭证授予

时间:2017-09-06 11:00:55

标签: spring security spring-security keycloak

我可以使用KecloakRestTemplate,其中一个keycloak客户端正在与另一个keycloak客户端进行通信。但是它只有在我登录到第一个keycloak客户端时才有效,即它将客户端ID,客户端密钥,用户名,密码发送到keycloak服务器。如果我没有在第一个客户端上使用用户和密码进行身份验证,我会收到“无法设置授权标头,因为没有经过验证的原则”。但是我已经将keycloak配置为使用第一个客户端的服务帐户(Client Credential Grant),因此我不应该使用用户/密码,而应仅依赖客户端ID /机密。这是OAuth 2规范的错误/偏离吗?

2 个答案:

答案 0 :(得分:2)

<!DOCTYPE html> <html> body> <body background="download.jpg"> <cfset name ="swanav"/> <cfoutput>#name#</cfoutput> </body> </html> 将客户端ID,客户端密钥,用户名和密码发送到Keycloak服务器。我只想发送客户端ID和密码。我创建了一个KeycloakRestTemplate KeycloakClientCredentialsRestTemplate子类来执行此操作。它在Spring Boot中使用OAuth2支持来执行客户端凭据授权。它还需要来自OAuth2RestTemplate的Keycloak属性。

application.properties

此外:

import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;

public class KeycloakClientCredentialsRestTemplate extends OAuth2RestTemplate {

    public KeycloakClientCredentialsRestTemplate(OAuth2ProtectedResourceDetails resource,
            OAuth2ClientContext context) {
        super(resource, context);
    }

}

答案 1 :(得分:0)

对于基于微服务架构的应用程序,我同时使用用户和service accounts。我猜Spring安全适配器只负责用户相关的东西(我使用的版本,至少是2.2.1)。我所做的就是拥有另一个RestTemplate,我自己处理这个问题,以便作为客户端访问资源。

举个例子:

@Service
public class RemoteAccessService{

    //Manages user access
    private KeycloakRestTemplate userAccessRestTemplate;

    //Manages client access
    private RestTemplate clientAccessRestTemplate;

    public RemoteAccessService(KeycloakRestTemplate userAccessRestTemplate, 
        @Qualifier("clientAccessRestTemplate") RestTemplate clientAccessRestTemplate;){

    }

}

然后,在RestTemplate类中构建一个@Configuration bean以管理客户端授权:

@Bean
public RestTemplate clientAccessRestTemplate() {
    RestTemplate template = new RestTemplate();
    template.getMessageConverters().add(new FormHttpMessageConverter());
    template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
    template.getInterceptors().add(new ClientHttpRequestInterceptor() {

        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body,
                ClientHttpRequestExecution execution) throws IOException {
            //Intercept each of the requests performed by this template 
            //and add the client access token in the Authorization header
            HttpRequest wrapper = new HttpRequestWrapper(request);
            if (clientAccessToken != null) {
                wrapper.getHeaders().set("Authorization",
                        "Bearer " + clientAccessToken.getToken());
            }
            return execution.execute(wrapper, body);
        }
    });
    return template;
}

当然,你需要确保在拦截器中有一个合适的clientAccessToken,否则你将获得401或403代码。在这里,你有一个关于如何在OAuth中执行此操作的post(您不需要用户/密码,只需要客户端凭据)。

作为旁注,keycloak适配器可以方便地管理某些情况,但它们无法访问keycloak的所有功能,这是一种更强大的功能。