我尝试使用路由器和处理程序类制作spring webflux安全应用程序。首先,以下代码是webflux安全性的配置代码。
@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();
}
}
接下来的代码是关于路由器类的。
@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);
}
}
即使网络是静止的Web服务,但我使用的是WebFlux的WebClient类。
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
我不使用卷曲。所以我想知道我的WebClient方法是什么,必须在其中找到用户名和密码并将其传输到WebClient类。任何答复将是感激的。
答案 0 :(得分:6)
从Spring 5.1开始,您应该使用HttpHeaders#setBasicAuth
设置基本身份验证,如下所示:
webClient
.get()
.uri("https://example.com")
.headers(headers -> headers.setBasicAuth("username", "password"))
.exchange()
....
答案 1 :(得分:2)
HTTP基本身份验证需要在Authorization
标头中以Base64格式编码的用户名和密码。另外,您不需要登录端点,因为此信息应随每个请求一起发送。
将基本身份验证标头添加到客户端中的每个呼叫,如下所示:
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()));
答案 2 :(得分:2)
Spring提供了API,用于通过ClientFilters向您的WebClient提供基本的身份验证参数。
使用更少的自定义编码来设置Authorization
标头可以达到相同的结果。
请参阅spring docs中的以下代码片段:
import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
WebClient client = WebClient.builder()
.filter(basicAuthentication("user", "password"))
.build();