Spring Webflux 的 WebClient 的用户名和密码放在哪里?
where to put username and password of WebClient of Spring Webflux?
我尝试使用路由器和处理程序 classes 制作 spring webflux 安全应用程序。首先,以下代码是webflux security的配置代码。
@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();
}
}
接下来的代码是关于路由器的 classe.
@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);
}
}
连网络都是rest web服务,但是我用的是WebFlux的WebClient class。
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()));
}
因为我做了webflux的安全配置,肯定有一些webclient不能执行和禁止如下,
Login : Unauthorized
User Creation: Forbidden
我不使用 curl。所以我想知道我的 WebClient 方法是什么,必须在其中找到用户名和密码并将其传输到 WebClient class。任何答复将不胜感激。
HTTP 基本身份验证需要 Authorization
header 中以 Base64 格式编码的用户名和密码。此外,您不需要登录端点,因为此信息应随每个请求一起发送。
将基本身份验证 header 添加到客户端中的每个调用,如下所示:
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()));
Spring 提供 API 通过 ClientFilters.
向您的 WebClient 提供基本身份验证参数
您可以使用较少的自定义编码实现 Authorization
header 设置的相同结果。
请参阅下面来自 spring 文档的代码片段:
import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
WebClient client = WebClient.builder()
.filter(basicAuthentication("user", "password"))
.build();
从 spring 5.1 开始,您应该使用 HttpHeaders#setBasicAuth
设置基本身份验证,如下所示:
webClient
.get()
.uri("https://example.com")
.headers(headers -> headers.setBasicAuth("username", "password"))
.exchange()
....
以前使用 .filter(basicAuthentication("user", "password")
的方法现已弃用。
我尝试使用路由器和处理程序 classes 制作 spring webflux 安全应用程序。首先,以下代码是webflux security的配置代码。
@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();
}
}
接下来的代码是关于路由器的 classe.
@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);
}
}
连网络都是rest web服务,但是我用的是WebFlux的WebClient class。
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()));
}
因为我做了webflux的安全配置,肯定有一些webclient不能执行和禁止如下,
Login : Unauthorized
User Creation: Forbidden
我不使用 curl。所以我想知道我的 WebClient 方法是什么,必须在其中找到用户名和密码并将其传输到 WebClient class。任何答复将不胜感激。
HTTP 基本身份验证需要 Authorization
header 中以 Base64 格式编码的用户名和密码。此外,您不需要登录端点,因为此信息应随每个请求一起发送。
将基本身份验证 header 添加到客户端中的每个调用,如下所示:
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()));
Spring 提供 API 通过 ClientFilters.
向您的 WebClient 提供基本身份验证参数您可以使用较少的自定义编码实现 Authorization
header 设置的相同结果。
请参阅下面来自 spring 文档的代码片段:
import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
WebClient client = WebClient.builder()
.filter(basicAuthentication("user", "password"))
.build();
从 spring 5.1 开始,您应该使用 HttpHeaders#setBasicAuth
设置基本身份验证,如下所示:
webClient
.get()
.uri("https://example.com")
.headers(headers -> headers.setBasicAuth("username", "password"))
.exchange()
....
以前使用 .filter(basicAuthentication("user", "password")
的方法现已弃用。