我正在编写一个 Spring Boot shell 应用程序,它应该访问受 keycloak 保护的 REST API。在网络应用程序中一切都很好。浏览器将我重定向到 keycloak,然后将 keycloak 返回到我的应用程序,瞧,我已通过身份验证。
但是在没有浏览器的Cli/Shell应用程序中这似乎是不可能的。
我想要的只是获取一个访问令牌并将其附加到每个休息请求。像这样:
POST {{realmUri}}/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded
Accept: application/json
grant_type=password
&username={{username}}
&password={{userPassword}}
&client_id={{clientId}}
&client_secret={{clientSecret}}
&scope=openid+phone
返回访问令牌。我如何通过 spring security oauth 实现这一点? “资源所有者密码流程”应该是正确的,但没有实施。
但我认为这一定是可能的。
也许 OAuth2LoginAuthenticationProvider 可以完成这项工作。
您可以使用 Spring Boot 中的 RestTemplate 向 Keycloak 令牌端点发送带有必要参数(grant_type、用户名、密码等)的 POST 请求,然后从响应中提取访问令牌并将其附加到您的 REST API 请求作为身份验证的承载令牌。
我找到了一个解决方案,当然这种方式已被弃用。有人有更好的主意吗?如何使用未弃用的类实现相同的目标?
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.oauth2.client.OAuth2AuthorizationContext;
import org.springframework.security.oauth2.client.PasswordOAuth2AuthorizedClientProvider;
import lombok.RequiredArgsConstructor;
@SpringBootApplication
@Configuration
@RequiredArgsConstructor
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
private final OAuth2ClientProperties tokenServiceProperties;
public String login(String username, String password) {
var clientConfig = new OAuth2ClientPropertiesMapper(tokenServiceProperties).asClientRegistrations();
OAuth2AuthorizationContext oAuth2AuthorizeContext = OAuth2AuthorizationContext
.withClientRegistration(clientConfig.get("keycloak")).attributes(attrs -> {
attrs.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username);
attrs.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password);
attrs.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
}).principal(new UsernamePasswordAuthenticationToken("no", "matter")).build();
var user = new PasswordOAuth2AuthorizedClientProvider().authorize(oAuth2AuthorizeContext);
return user.getAccessToken().getTokenValue();
}
@Bean
CommandLineRunner run() {
System.out.println(login("myapp_user_user", "password"));
return aa -> {
};
}
}