spring security 在 spring webflux 中的使用
spring5增加了reactive web模組,相應的在spring security中也增加了 [webflux-web-security] 模組,相對於spring security 在配置和使用方面有略微的差異,下面主要說明簡單的配置和自定義使用者資訊的配置。
1、基本配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
@Configuration
@EnableWebFluxSecurity
public class WebFluxSecurityConfig{
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange()
//.pathMatchers("/loginPage").permitAll() //無需進行許可權過濾的請求路徑
.anyExchange().authenticated()
.and()
.httpBasic().and()
.formLogin()
//.loginPage("/loginPage") //自定義的登陸頁面
;
return http.build();
}
}
以上配置為官方文件給出的基本配置,在專案啟動的會有一串加密資訊
Using generated security password: 38bb8fb7-fd82-4bfc-8243-8e23a5ab879c
就是專案預設的使用者名稱是:user,密碼為上面這一串資訊
這裡寫圖片描述
2、自定義使用者資訊
上面的配置只有一個使用者資訊,如何使用資料庫中的使用者資訊呢? [官方文件] 給出的預設配置如下
@EnableWebFluxSecurity
public class HelloWebfluxSecurityConfig {
@Bean
public MapReactiveUserDetailsService userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("user")
.roles("USER")
.build();
return new MapReactiveUserDetailsService(user);
}
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange()
.anyExchange().authenticated()
.and()
.httpBasic().and()
.formLogin();
return http.build();
}
}
在上述方面中User.withDefaultPasswordEncoder()已經被標註為@Deprecated,並且這種方式在專案啟動的時候把使用者給定死了仍不夠靈活。
在spring-webflux-security中提供了一個介面 ReactiveUserDetailsService,官方文件給出的MapReactiveUserDetailsService就是實現這個介面,所以我們依樣畫葫蘆實現這個介面就能使用資料庫中的使用者資訊了。
public interface ReactiveUserDetailsService {
/**
* Find the {@link UserDetails} by username.
* @param username the username to look up
* @return the {@link UserDetails}. Cannot be null
*/
Mono<UserDetails> findByUsername(String username);
}
具體程式碼如下
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.jokerchen.reactiveWeb.service.UserService;
import reactor.core.publisher.Mono;
public class WebReactiveUserDetailsService
implements ReactiveUserDetailsService{
@Autowired
private UserService userService;
@Override
public Mono<UserDetails> findByUsername(String username) {
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
com.jokerchen.reactiveWeb.entity.User defUser = userService.findUserByUsername(username);
UserDetails user = User.withUsername(defUser.getUsername())
.password(encoder.encode(defUser.getPassword()))
.roles(defUser.getRole())
.build();
return Mono.just(user);
}
}