java—有没有更好的方法用SpringRSocket实现oauth2客户端凭据?

w41d8nur  于 2021-07-06  发布在  Java
关注(0)|答案(0)|浏览(267)

我有两个springboot应用程序,一个springboot rsocket客户端应用程序和一个springboot rsocket服务器应用程序。我正试图通过使用key斗篷来增加oauth2和oidc的安全性。从我读到的内容来看,客户机凭证流似乎是服务对服务通信的最佳选择,所以这就是我一直在研究的内容。
到目前为止,我通过rsocket客户端应用程序上的以下代码实现了这一点:

@EnableWebFluxSecurity
public class WebFluxSecurityConfiguration {

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
        return http
                .csrf().disable()
                .authorizeExchange()
                .pathMatchers("/api/v1/**").permitAll()
                .and().oauth2Client()
                .and().oauth2ResourceServer().jwt()
                .and().and()
                .build();
    }

}

@Component
@RequiredArgsConstructor
public class OAuth2 {

    private final ReactiveClientRegistrationRepository clientRepository;

    @Value("${oauth2.client.registration-id}")
    private String clientRegistrationId;

    public Mono<String> getAccessToken() {
        var client = new WebClientReactiveClientCredentialsTokenResponseClient();
        return clientRepository
                .findByRegistrationId(clientRegistrationId)
                .map(OAuth2ClientCredentialsGrantRequest::new)
                .flatMap(client::getTokenResponse)
                .map(OAuth2AccessTokenResponse::getAccessToken)
                .map(OAuth2AccessToken::getTokenValue);
    }

    public Consumer<RSocketRequester.MetadataSpec<?>> addTokenToMetadata(String token) {
        var mimeType = MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_AUTHENTICATION.getString());
        var bearerTokenMetadata = new BearerTokenMetadata(token);
        return spec -> spec.metadata(bearerTokenMetadata, mimeType);
    }

}

@Component
public class FooClientImpl implements FooClient {

    private final Mono<RSocketRequester> rsocketRequester;
    private final OAuth2 oAuth2;

    public FooClientImpl(RSocketRequester.Builder requesterBuilder,
                         OAuth2 oAuth2,
                         @Value("${routes.foo-service.host}") String host,
                         @Value("${routes.foo-service.port}") Integer port) {

        this.rsocketRequester = requesterBuilder
                .rsocketStrategies(configurer -> configurer.encoder(new BearerTokenAuthenticationEncoder()))
                .dataMimeType(MediaType.APPLICATION_CBOR)
                .connectTcp(host, port);

        this.oAuth2 = oAuth2;
    }

    @Override
    public Publisher<Foo> findFoos(FooRequest request) {
        return oAuth2.getAccessToken()
                .flatMapMany(accessToken -> rsocketRequester
                        .flatMapMany(req -> req
                                .route("find.foos")
                                .metadata(oAuth2.addTokenToMetadata(accessToken))
                                .data(request)
                                .retrieveFlux(Foo.class)));
    }
}

my application.yml配置文件:

server:
  port: 9000

logging:
  level:
    root: info

---

spring:
  profiles: local
  security:
    oauth2:
      client:
        provider:
          keycloak:
            issuer-uri: http://localhost:8080/auth/realms/foo
        registration:
          keycloak:
            client-id: foo-service
            client-secret: 81196896-80bd-41e3-97e6-3556feeef577
            authorization-grant-type: client_credentials
      resourceserver:
        jwt:
          issuer-uri: http://localhost:8080/auth/realms/foo

routes:
  foo-service:
    host: localhost
    port: 7000

oauth2:
  client:
    registration-id: keycloak

尽管例如,如果我使用http而不是rsocket,我还是可以像这样利用spring的webclient:

@Bean
WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations,
                    ServerOAuth2AuthorizedClientRepository authorizedClients) {
    var oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);
    oauth.setDefaultClientRegistrationId("keycloak");
    return WebClient
            .builder()
            .filter(oauth)
            .build();
}

有没有更好的方法来实现这一点?有没有一种方法可以通过过滤函数(或类似的函数)用访问令牌调用rsocket服务器(通过rsocketrequester),就像我对webclient所做的那样?spring security rsocket中是否支持oauth2客户端?我已经查阅了springrsocket文档,但是它们只提到了一般的jwt支持,我没有找到任何关于oauth2支持的内容。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题