1.首先在网关pom中引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- JWT依赖 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.0.9.RELEASE</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<!-- 引入Redis场景启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
2.创建WebSecurityConfig
@EnableWebFluxSecurity
@Configuration
@Slf4j
public class WebSecurityConfig {
@Autowired
SecurityUserDetailsService securityUserDetailsService;
@Autowired
AuthorizationManager authorizationManager;
@Autowired
AccessDeniedHandler accessDeniedHandler;
@Autowired
AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
AuthenticationFaillHandler authenticationFaillHandler;
// @Autowired
// SecurityRepository securityRepository;
@Autowired
RedisToHeadersFilter redisToHeadersFilter;
@Autowired
LogoutSuccessHandler logoutSuccessHandler;
@Autowired
LogoutHandler logoutHandler;
@Autowired
AuthenticationEntryPoint authenticationEntryPoint;
private final String[] path={
"/favicon.ico",
"/book/**",
"/user/__MACOSX/**",
"/user/css/**",
"/user/fonts/**",
"/user/images/**"};
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.addFilterAt(redisToHeadersFilter, SecurityWebFiltersOrder.HTTP_HEADERS_WRITER);
//SecurityWebFiltersOrder枚举类定义了执行次序
// http.authorizeExchange(exchange -> exchange // 请求拦截处理
// .pathMatchers(path).permitAll()
// .pathMatchers(HttpMethod.OPTIONS).permitAll()
// .anyExchange().access(authorizationManager)//权限
// //.and().authorizeExchange().pathMatchers("/user/normal/**").hasRole("ROLE_USER")
// //.and().authorizeExchange().pathMatchers("/user/admin/**").hasRole("ROLE_ADMIN")
// //也可以这样写 将匹配路径和角色权限写在一起
// )
http.authorizeExchange()
.pathMatchers(path).permitAll()
// .pathMatchers(HttpMethod.OPTIONS).permitAll()
.anyExchange().access(authorizationManager)//权限
.and()
.httpBasic()
.and()
.formLogin().loginPage("/user/login")//登录接口
.authenticationSuccessHandler(authenticationSuccessHandler) //认证成功
.authenticationFailureHandler(authenticationFaillHandler) //登陆验证失败
.and().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler)//基于http的接口请求鉴权失败
.and().csrf().disable()//必须支持跨域
.logout().logoutUrl("/user/logout")
.logoutHandler(logoutHandler)
.logoutSuccessHandler(logoutSuccessHandler);
// http.securityContextRepository(securityRepository);
//http.securityContextRepository(NoOpServerSecurityContextRepository.getInstance());//无状态 默认情况下使用的WebSession
return http.build();
}
@Bean
public ReactiveAuthenticationManager reactiveAuthenticationManager() {
LinkedList<ReactiveAuthenticationManager> managers = new LinkedList<>();
managers.add(authentication -> {
// 其他登陆方式
return Mono.empty();
});
managers.add(new UserDetailsRepositoryReactiveAuthenticationManager(securityUserDetailsService));
return new DelegatingReactiveAuthenticationManager(managers);
}
}
3.根据2中的config分别创建引用的组件
(1)创建SecurityUserDeta