要求是使用WebClient从java客户端程序调用OAuth保护的endpoint。我使用的是使用反应对象的密码授权类型。请注意,我是反应编程模式的新手。当我调用webclient时,我得到以下错误**serverWebExchange不能为空**
String data = webClient
.post().uri(endPoint)
// This will add the Authorization header with the bearer token.
.attributes(ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId("custom"))
.body(Mono.just(alert), Alert.class)
.retrieve()
.bodyToMono(String.class)
// Block until we receive a response for a non-reactive client.
.block();
java.lang.IllegalArgumentException: serverWebExchange cannot be null
at org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager.lambda$loadAuthorizedClient$9(DefaultReactiveOAuth2AuthorizedClientManager.java:102)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ Request to POST http://<hostname>/<protected_endpoint> [DefaultWebClient]
Stack trace:
at org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager.lambda$loadAuthorizedClient$9(DefaultReactiveOAuth2AuthorizedClientManager.java:102)
at reactor.core.publisher.MonoErrorSupplied.subscribe(MonoErrorSupplied.java:70)
at reactor.core.publisher.Mono.subscribe(Mono.java:4210)
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onComplete(FluxSwitchIfEmpty.java:75)
.....
at reactor.core.publisher.Mono.block(Mono.java:1665)
at com.xxxxx.oauthclient.ApplicationTests.testWebClient(ApplicationTests.java:41)
....
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Suppressed: java.lang.Exception: #block terminated with an error
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99)
at reactor.core.publisher.Mono.block(Mono.java:1666)
at com.xxxx.oauthclient.ApplicationTests.testWebClient(ApplicationTests.java:41)
....
@Configuration
public class ReactiveOAuthConfig {
@Value("${oauth.username}") String username;
@Value("${oauth.password}") String password;
@Bean
WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
return WebClient.builder()
.filter(oauth)
.build();
}
@Bean
ReactiveOAuth2AuthorizedClientManager reactiveOAuth2AuthorizedClientManager(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {
ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.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();
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);
};
}
spring.security.oauth2.client.provider.custom.token-uri=https://endpoint_to_get_token
spring.security.oauth2.client.registration.custom.client-id=<clientid>
spring.security.oauth2.client.registration.custom.client-secret=<client-secret>
spring.security.oauth2.client.registration.custom.client-authentication-method=post
spring.security.oauth2.client.registration.custom.authorization-grant-type=password
spring.security.oauth2.client.registration.custom.scope=AppIdClaimsTrust
注意:如https://github.com/jgrandja/spring-security-oauth-5-2-migrate/tree/master/client-app所述,我能够验证从web客户端调用Oauth受保护的endpoint
生成ReactiveOAuth2AuthorizedClientProvider时,不应使用authorizationCode。和刷新令牌不应用于计算机到计算机的通信。
最重要的是不要使用DefaultReactiveoAuth2AuthorizedClientManager。取而代之的是使用
AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
我正在使用Spring构建Web应用程序。我有多个Spring客户端应用程序和一个OAuth2授权和资源服务器。最终用户首先在客户端应用内进行身份验证,然后客户端应用从资源服务器请求一些资源(从授权服务器获得访问令牌后),处理数据并将其返回给用户。用户也可以更改资源服务器上的数据,但只能通过客户端应用。对于仅使用客户端凭证的资源获取,在这种情况下资源所有者是可信客户端。 在资源服务器上,仅存储客户
出于学习目的,我正在使用OAuth2开发一个REST API Angular 4应用程序。 有些受保护的endpoint只能由经过身份验证的用户调用。让我们以更新用户配置文件的endpoint为例: /users/{user_id} 登录用户将能够通过转到更新配置文件屏幕来更新自己的配置文件,该屏幕在后台将调用 /users/{user_id}发送带有新信息和访问令牌的有效载荷。 我们如何防止恶意
我如何保护我的javascript客户端,你能推荐一些库吗。 提前谢谢你
我们有一个应用程序,它使用Azure Spring Boot Active Directory starter“com.microsoft.Azure:Azure Active Directory Spring Boot starter”和Spring Security来保护对该应用程序的访问。这一切都很好。 这是按照以下说明完成的: https://docs.microsoft.com/en-u
我有一个API,我想与OAuth2安全。我已经用密码做了一个虚拟测试grant_type一切正常。我可以请求令牌,用它访问安全的endpoint,等等。服务器充当授权和资源服务器。 后来我读到,我应该使用隐式的grant_类型,因为客户端将是一个javascript应用程序。 我的客户端是这样配置的: 如果我尝试像这样访问endpoint:http://localhost:8080/oauth/a
快速入门展示了使用 IdentityServer 保护 API 的最基础的场景。 在这个场景中,我们定义一个 API,同时定义一个 想要访问这个 API 的 客户端。客户端将从 IdentityServer 请求获得一个访问令牌,然后用这个令牌来获得 API 的访问权限。 定义 API 范围(Scopes)用来定义系统中你想要保护的资源,比如 API。 由于当前演练中我们使用的是内存配置 —— 添