[英]How to switch to a service user when using Spring Oauth2RestTemplate
I am trying to use Spring's Oauth2RestTemplate, but we need it to use some super user when making a Rest call (we have the user defined), rather than it passing through the user that originally made the service call.我正在尝试使用 Spring 的 Oauth2RestTemplate,但是在进行 Rest 调用(我们已经定义了用户)时,我们需要它使用一些超级用户,而不是通过最初进行服务调用的用户。
So here's the situation:所以情况如下:
userA
makes a call to endpointA
. userA
调用endpointA
。 Naturally, he has permission to hit this endpoint (based on permitted actions in his assigned roles in Keycloak).自然,他有权访问此端点(基于他在 Keycloak 中分配的角色中允许的操作)。 endpointA
will then make a Rest call using the OAuth2RestTemplate to another service, endpointB
.然后, endpointA
将使用 OAuth2RestTemplate 对另一个服务endpointB
进行 Rest 调用。 However, userA
does not have permission to hit that endpoint.但是, userA
无权访问该端点。 This call should be made as a service-user
, who in our keycloak, is essentially a super user that can do anything.这个调用应该作为service-user
进行,在我们的 keycloak 中,他本质上是一个可以做任何事情的超级用户。 The problem is, the OAuth2RestTemplate is keeping the same user that made the original call ( userA
) - since he is not permitted to access that endpoint, the call fails (based on RBAC stuff we have set up, separate from the Oauth2 security side of things).问题是,OAuth2RestTemplate 保留了进行原始调用( userA
)的同一用户 - 因为他不允许访问该端点,所以调用失败(基于我们设置的 RBAC 内容,与 Oauth2 安全方面分开事物)。
Is there a way to hit an endpoint using userA
, who has limited access, and have it trigger making a REST call through the OAuth2RestTemplate using a service-user
that has access to everything?有没有办法使用访问权限受限的userA
访问端点,并使用有权访问所有内容的service-user
通过 OAuth2RestTemplate 触发 REST 调用? Note: the OAuth2 info for that service-user
should still be retrieved the same as it would be as if it were still userA
(lookup in keycloak).注意:该service-user
的 OAuth2 信息仍应被检索,就像它仍然是userA
一样(在 keycloak 中查找)。 Essentially, this would just be us changing the username before making the REST call (well... I think that's what it entails).本质上,这只是我们在调用 REST 之前更改用户名(嗯......我认为这就是它所需要的)。
Note: I found a way to temporarily get passed this.注意:我找到了一种暂时通过这个的方法。 That is by creating a new thread before making the REST call.即在调用 REST 之前创建一个新线程。 This works because Spring no longer has access to the user's security context in that new thread, forcing it to retrieve a new token using the security details provided when creating the OAuth2RestTemplate.这是因为 Spring 不再有权访问该新线程中的用户安全上下文,迫使它使用创建 OAuth2RestTemplate 时提供的安全详细信息检索新令牌。 This shows that another solution (and actually preferred) would be to force the OAuth2RestTemplate to always retrieve a new token when hit (using the ResourceDetails, not a "refresh" of the user's token), rather than using the one stored in the SecurityContextHolder at the start of the request.这表明另一种解决方案(实际上是首选)是强制 OAuth2RestTemplate 在命中时始终检索新令牌(使用 ResourceDetails,而不是用户令牌的“刷新”),而不是使用存储在 SecurityContextHolder 中的令牌请求的开始。
I ended up just clearing the context before making the REST call:在进行 REST 调用之前,我最终只是清除了上下文:
SecurityContextHolder.clearContext()
When the OAuth2RestTemplate goes to make the call, it will check to see if Authentication has been done through that holder.当 OAuth2RestTemplate 进行调用时,它将检查是否已通过该持有者完成身份验证。 If it does not see a token (which is the case when you clear the context), it will look up a new token using the OAuth2 configuration defined in the ResourceDetails.如果它没有看到令牌(当您清除上下文时就是这种情况),它将使用 ResourceDetails 中定义的 OAuth2 配置查找新令牌。 Just make sure that it references a client that has the permissions required.只需确保它引用具有所需权限的客户端即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.