1
votes

où mettre le nom d'utilisateur et le mot de passe de WebClient of Spring Webflux?

J'essaie de créer une application de sécurité Spring Webflux avec des classes de routeurs et de gestionnaires. Tout d'abord, les codes ci-dessous sont les codes de configuration de la sécurité webflux.

Login : Unauthorized
User Creation: Forbidden

Et les codes suivants concernent la classe de routeur.

public void functionOnUserDocument() { 
        client.get().uri("/route/user/all").accept(MediaType.APPLICATION_JSON).exchange()
                .flatMapMany(response -> response.bodyToFlux(User.class))
                .subscribe(u -> System.out.println("All Users : " + u.getUsername() + ":" + u.getEmail() + ":" + u.getFullname()));

        client.get().uri("/route/user/id/{id}", "0002").accept(MediaType.APPLICATION_JSON).exchange()
                .flatMap(response -> response.bodyToMono(User.class))
                .subscribe(u -> System.out.println("GET by Id : " + u.getUsername() + ":" + u.getEmail() + ":" + u.getFullname()));

        client.get().uri("/route/user/username/{username}", "jina").accept(MediaType.APPLICATION_JSON).exchange()
                .flatMap(response -> response.bodyToMono(User.class))
                .subscribe(u -> System.out.println("Get by username : " + u.getUsername() + ":" + u.getEmail() + ":" + u.getFullname()));

        client.get().uri("/route/user/email/{email}", "myson@college.ac.kr").accept(MediaType.APPLICATION_JSON).exchange()
                .flatMap(response -> response.bodyToMono(User.class))
                .subscribe(u -> System.out.println("Get By Email : " + u.getUsername() + ":" + u.getEmail() + ":" + u.getFullname()));

        client.get().uri("/route/user/login/{username}/{password}", "julian", "password").exchange()
                .map(ClientResponse::statusCode).subscribe(response -> System.out.println("Login : " + response.getReasonPhrase()));

        User user = new User("0005", 4L, "jane", "password", "aaa@bbb.com", "누나", "USER");

        client.post().uri("/route/user/create").body(Mono.just(user), User.class).exchange() 
                .map(ClientResponse::statusCode).subscribe(response -> System.out.println("User Creation: " + response.getReasonPhrase()));
    }

Même le network est un service web de repos, mais j'utilise la classe WebClient de WebFlux.

@Configuration
@EnableWebFlux
public class BlogWebFluxEndpointRouter {

    @Bean
    public RouterFunction<ServerResponse> routesUser(UserHandler handler) {

        return RouterFunctions.route(RequestPredicates.GET("/route/user/all"), handler::findAll)
                    .andRoute(RequestPredicates.GET("/route/user/id/{id}"), handler::findById)
                    .andRoute(RequestPredicates.GET("/route/user/username/{username}"), handler::findByUsername)
                    .andRoute(RequestPredicates.GET("/route/user/email/{email}"), handler::findByEmail)
                    .andRoute(RequestPredicates.POST("/route/user/create"), handler::register)
                    .andRoute(RequestPredicates.GET("/route/user/login/{username}/{password}"), handler::authenticate);
    }

    @Bean
    public RouterFunction<ServerResponse> routesPost(PostHandler handler) {

        return RouterFunctions.route(RequestPredicates.GET("/route/post/all"), handler::findAll)
                    .andRoute(RequestPredicates.GET("/route/post/id/{id}"), handler::findById)
                    .andRoute(RequestPredicates.GET("/route/post/delete/{id}"), handler::deleteById)
                    .andRoute(RequestPredicates.POST("/route/post/create"), handler::create)
                    .andRoute(RequestPredicates.PUT("/route/post/{id}/{content}"), handler::edit);
    }
}

Parce que je fais la configuration de sécurité webflux, certains webclient ne peuvent certainement pas être exécutés et interdits comme ci-dessous,

@Configuration
@EnableWebFluxSecurity
public class BlogWebFluxSecurityConfig {

    @Bean
    public MapReactiveUserDetailsService userDetailsService() {

        UserDetails userWebFlux = User.withUsername("joseph").password("password").roles("USER").build();
        return new MapReactiveUserDetailsService(userWebFlux);
    }

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http
        .authorizeExchange()
        .pathMatchers("/route/user/all", "/route/post/all").permitAll()
        .pathMatchers(HttpMethod.GET, "/route/user/**", "/route/post/**").hasRole("USER")
        .anyExchange().authenticated()
        .and()
        .httpBasic();

        return http.build();
    } 
}

Je n'utilise pas curl. Donc, ce que je veux savoir, c'est ce que doivent être mes méthodes WebClient, où le nom d'utilisateur et le mot de passe doivent être localisés et transférés vers la classe WebClient. Toute réponse sera reconnaissante.


4 commentaires

vous avez plusieurs mauvaises choses dans votre code, vous ne vous abonnez JAMAIS à une application webflux donc tout abonnement doit être supprimé. Et je n'ai aucune idée de votre question. Est-ce lorsque les gens appellent votre service ou lorsque votre service appelle un autre service?


Merci pour votre réponse. Tu veux dire quelle partie de ma source a une mauvaise chose? Routeur ou WebClient? Veuillez m'informer du site de référence ainsi que de mes erreurs.


votre service est un éditeur , tous les clients qui l'appellent sont des abonnés . Vous ne devez donc pas utiliser subscribe


vous ne devriez jamais / route / user / login / {username} / {password} cela enverra gratuitement les noms d'utilisateur et les mots de passe sur Internet pour que tout le monde puisse les voir security.stackexchange.com / questions / 142695 /…


3 Réponses :


4
votes

L'authentification HTTP Basic attend le nom d'utilisateur et le mot de passe encodés au format Base64 dans l'en-tête Authorization . De plus, vous n'avez pas besoin d'avoir un point de terminaison de connexion car ces informations doivent être envoyées avec chaque demande.

Ajoutez l'en-tête d'authentification de base à chaque appel dans votre client comme suit:

String basicAuthHeader = "basic " + Base64Utils.encodeToString((username + ":" + password).getBytes())

client.get().uri("/route/user/all")
      .accept(MediaType.APPLICATION_JSON)
      .header(HttpHeaders.AUTHORIZATION, basicAuthHeader)
      .exchange()
      .flatMapMany(response -> response.bodyToFlux(User.class))
      .subscribe(u -> System.out.println("All Users : " + u.getUsername() + ":" + u.getEmail() + ":" + u.getFullname()));


0 commentaires

2
votes

Spring fournit une API pour fournir des paramètres d'authentification de base à votre client Web via ClientFilters .

Vous pouvez obtenir le même résultat en configurant l'en-tête Authorization avec moins de codage personnalisé.

Veuillez consulter l'extrait de code ci-dessous tiré de la documentation du printemps:

import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;

    WebClient client = WebClient.builder()
            .filter(basicAuthentication("user", "password"))
            .build();


0 commentaires

7
votes

Depuis le printemps 5.1, vous devez définir l'authentification de base avec HttpHeaders # setBasicAuth , comme ceci:

webClient
    .get()
    .uri("https://example.com")
    .headers(headers -> headers.setBasicAuth("username", "password"))
    .exchange()
    ....

le approche précédente, consistant à utiliser .filter (basicAuthentication (" user "," password ") , est désormais obsolète. p>


0 commentaires