5. Reactive Spring Security
5.1 Reactive Spring Security原理
Spring MVC的Security是通过Servlet的Filter
实现的,而WebFlux的响应式Security是基于WebFilter
实现的,由一些列的WebFilter
形成的过滤器链。
-
认证
Spring WebFlux下的响应式安全和Spring MVC下的安全认证机制也是有概念对应的:
Spring WebFlux Security Spring Web MVC Security AuthenticationWebFilter
UsernamePasswordAuthenticationFilter
ReactiveAuthenticationManager
AuthenticationManager
UserDetailsRepositoryReactiveAuthenticationManager
ProviderManager
AuthenticationManager
ReactiveUserDetailsService
UserDetailsService
-
授权
授权也一样,概念上也是对应的:
Spring WebFlux Security Spring Security AuthorizationWebFilter
FilterSecurityInterceptor
ReactiveAuthorizationManager
AccessDecisionManager
-
其它对等的还有:
Spring WebFlux Security Spring Security @EnableWebFluxSecurity
@EnableWebSecurity
@EnableReactiveMethodSecurity
@EnableGlobalMethodSecurity
ReactiveSecurityContextHolder
SecurityContextHolder
5.2 Spring Boot的自动配置
Spring Boot为响应式安全提供了下面两个配置:
ReactiveSecurityAutoConfiguration
:使用@EnableWebFluxSecurity
开启Spring WebFlux安全的支持;ReactiveUserDetailsServiceAutoConfiguration
:配置一个reactiveUserDetailsService
的Bean。
下面我们将用一个例子来学习响应式的安全机制,它和我们前面学的Spring MVC下的安全用法是很类似的。
5.3 示例
5.1.3.1 新建应用
新建应用,信息如下:
Group:top.wisely
Artifact:learning-reactive-security
Dependencies:Spring Security
、Spring Reactive Web
、Spring Data Reactive MongoDB
、Lombok
build.gradle
文件中的依赖如下:
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
//...
}
Spring WebFlux Security和Spring MVC Security都在Spring Security中。
5.1.3.2 连接MongoDB
在application.yml
中配置连接MongoDB
spring:
data:
mongodb:
host: localhost
port: 27017
username: wisely
password: zzzzzz
database: first_db
5.1.3.3 定义领域模型
-
安全相关模型
@Data @AllArgsConstructor @NoArgsConstructor @Document(collection = "user") public class SysUser implements UserDetails { @Id private String id; private String username; private String password; private Set<SysAuthority> sysAuthorities; private Boolean enable = true; public SysUser(String username, String password, Set<SysAuthority> sysAuthorities) { this.username = username; this.password = password; this.sysAuthorities = sysAuthorities; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return this.sysAuthorities .stream() .map(authority -> new SimpleGrantedAuthority(authority.getName())) .collect(Collectors.toCollection(HashSet::new)); } //省略其它UserDetails接口方法 }
@Data @AllArgsConstructor @NoArgsConstructor public class SysAuthority { private String name; }
-
业务相关模型
-
@Data @AllArgsConstructor @NoArgsConstructor @Document(collection = "people") public class Person {