如何将Spring Cloud Gateway中的路由配置为使用具有authorization-grant-type:password
的OAuth2客户端?换句话说,如何将请求中带有令牌的授权头添加到API?因为我正在与遗留应用程序集成,所以必须使用grant类型密码。
我有这个申请:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("route_path", r -> r.path("/**")
.filters(f -> f.addRequestHeader("Authorization", "bearer <token>"))
.uri("http://localhost:8092/messages"))
.build();
}
}
用一个实际的令牌替换
,一切正常。
我发现这个项目做了类似的事情:https://github.com/jgrandja/spring-security-oauth-5-2-migrate。它有一个客户机(messaging-client-password
),用于配置WebClient
,以添加OAuth2支持来发出请求(即通过添加授权头)。
首先,我发现了如何将WebClientConfig
转换为反应性:
@Configuration
public class WebClientConfig {
@Bean
WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oauth.setDefaultOAuth2AuthorizedClient(true);
oauth.setDefaultClientRegistrationId("messaging-client-password");
return WebClient.builder()
.filter(oauth)
.build();
}
@Bean
ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.refreshToken()
.password()
.build();
DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
// For the `password` grant, the `username` and `password` are supplied via request parameters,
// so map it to `OAuth2AuthorizationContext.getAttributes()`.
authorizedClientManager.setContextAttributesMapper(contextAttributesMapper());
return authorizedClientManager;
}
private Function<OAuth2AuthorizeRequest, Mono<Map<String, Object>>> contextAttributesMapper() {
return authorizeRequest -> {
Map<String, Object> contextAttributes = Collections.emptyMap();
ServerWebExchange serverWebExchange = authorizeRequest.getAttribute(ServerWebExchange.class.getName());
String username = serverWebExchange.getRequest().getQueryParams().getFirst(OAuth2ParameterNames.USERNAME);
String password = serverWebExchange.getRequest().getQueryParams().getFirst(OAuth2ParameterNames.PASSWORD);
if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
contextAttributes = new HashMap<>();
// `PasswordOAuth2AuthorizedClientProvider` requires both attributes
contextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, username);
contextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password);
}
return Mono.just(contextAttributes);
};
}
}
通过这种配置,我们可以使用WebClient
发出请求。这在调用endpoint后以某种方式初始化OAuth2客户机:
@GetMapping("/explicit")
public Mono<String[]> explicit() {
return this.webClient
.get()
.uri("http://localhost:8092/messages")
.attributes(clientRegistrationId("messaging-client-password"))
.retrieve()
.bodyToMono(String[].class);
}
然后,通过调用这个函数,我们可以获得对授权客户机的引用:
private OAuth2AuthorizedClient authorizedClient;
@GetMapping("/token")
public String token(@RegisteredOAuth2AuthorizedClient("messaging-client-password") OAuth2AuthorizedClient authorizedClient) {
this.authorizedClient = authorizedClient;
return authorizedClient.getAccessToken().getTokenValue();
}
@Bean
public GlobalFilter customGlobalFilter() {
return (exchange, chain) -> {
//adds header to proxied request
exchange.getRequest().mutate().header("Authorization", authorizedClient.getAccessToken().getTokenType().getValue() + " " + authorizedClient.getAccessToken().getTokenValue()).build();
return chain.filter(exchange);
};
}
ContextAttributesMapper
我使用WebClienthtTProutingFilter
实现了authorization-grant-type:password。
默认情况下,spring cloud gateway使用Netty Routing Filter,但也有一种不需要Netty的选择(https://cloud.spring.io/spring-cloud-gateway/reference/html/#the-netty-routing-filter)
WebClienthtTProutingFilter
使用WebClient
路由请求。
WebClient
可以通过ExchangeFilterFunction
(https://docs.spring.io/spring-security/site/docs/current/reference/html5/#WebClient)配置ReactiveOAuth2AuthorizedClientManager
。ReactiveOAuth2AuthorizedClientManager
将负责管理访问/刷新令牌,并为您完成所有艰巨的工作
在这里,您可以回顾这个实现。此外,我用这种方法实现了客户机凭据授予
应用程序需要连接到仅支持OAuth2资源所有者密码凭据授予的API。我尝试使用下面的代码,但得到的响应代码为400“错误请求”。使用相同的代码,我可以连接到一个正常的网站并检索内容。 我知道API代码是工作,因为使用邮递员工作。在邮递员中,我只是发出一个帖子请求,提供用户名、密码和grant_type,并使用x-www. form-urlencoded 连接的返回是一个json。 你知道怎么了吗?
本文向大家介绍oauth 资源所有者密码凭证授予,包括了oauth 资源所有者密码凭证授予的使用技巧和注意事项,需要的朋友参考一下 示例 资源
关于使用OAuth2的spring-cloud-security我有两个问题: > 如何通过grant_type保护资源?我想用client_credentials保护我的REST API,然后通过密码授权类型保护用户特定的资源。这可能吗? 与本教程相一致的是,密码授予类型不需要客户端秘密,尽管spring cloud oauth2似乎总是需要客户端秘密。我怎么处理这个?通过设置一个像“ABC”这
null 用户在登录表单中输入凭据->应用程序1将使用用户凭据从应用程序2获取令牌,其具有密码授予类型->使用令牌访问应用程序1的资源。 问题是Spring Security 5是否支持客户端的密码授予类型?我在Spring Security 5实现中找到了所有rest授予类型,但没有找到密码。
资源所有者密码凭据(即用户名和密码),可以直接作为获取访问令牌的授权许可。这种凭据只能应该当资源所有者和客户端之间具有高度信任时(例如,客户端是设备的操作系统的一部分,或者是一个高度特权应用程序),以及当其他授权许可类型(例如授权码)不可用时被使用。 尽管本授权类型需要对资源所有者凭据直接的客户端访问权限,但资源所有者凭据仅被用于一次请求并被交换为访问令牌。通过凭据和长期有效的访问令牌或刷新令牌的
我一直在广泛阅读有关OAuth和OpenID Connect的内容,但此问题专门涉及OAuth2资源所有者密码授予(又名OAuth2资源所有者凭据授予,又名OAuth2密码授予) 某些资源(例如Justin Richer的《OAuth2 in Action》一书)说不要使用OAuth2资源所有者密码授予进行身份验证-请参阅书中的第6.1.3节。 以下其他好资源都说我们可以使用OAuth2资源所有者