IT评测·应用市场-qidao123.com技术社区
标题:
SpringSecurity5(14-Gateway整合)
[打印本页]
作者:
傲渊山岳
时间:
2025-4-8 08:16
标题:
SpringSecurity5(14-Gateway整合)
MVC 与 WebFlux 关系
SpringSecurity 设置要采用响应式配置,基于 WebFlux 中 WebFilter 实现,与 Spring MVC 的 Security 是通过 Servlet 的 Filter 实现雷同,也是一系列 filter 组成的过滤链。
Reactor 与传统 MVC 配置对应:
webfluxmvc作用@EnableWebFluxSecurity@EnableWebSecurity开启 security 配置ServerAuthenticationSuccessHandlerAuthenticationSuccessHandler登录乐成 HandlerServerAuthenticationFailureHandlerAuthenticationFailureHandler登录失败 HandlerServerLogoutSuccessHandlerLogoutSuccessHandler注销乐成HandlerServerSecurityContextRepositorySecurityContextHolder认证信息存储管理ReactiveUserDetailsServiceUserDetailsService用户登录逻辑处置惩罚ReactiveAuthenticationManagerAuthorizationManager认证管理ReactiveAuthorizationManagerAccessDecisionManager鉴权管理ServerAuthenticationEntryPointAuthenticationEntryPoint未认证 HandlerServerAccessDeniedHandlerAccessDeniedHandler鉴权失败 HandlerAuthenticationWebFilterFilterSecurityInterceptor拦截器
快速入门
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.38</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
复制代码
内存管理用户信息
@EnableWebFluxSecurity
@Configuration
public class SecurityConfig {
@Bean
public SecurityWebFilterChain filterChain(ServerHttpSecurity http) {
http.httpBasic()
.and()
.authorizeExchange()
.anyExchange()
.authenticated();
return http.build();
}
/**
* 内存管理用户信息
*/
@Bean
public MapReactiveUserDetailsService userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new MapReactiveUserDetailsService(user);
}
}
复制代码
自定义登录、注销处置惩罚器
自定义登录乐成处置惩罚器
@Component
public class LoginSuccessHandler implements ServerAuthenticationSuccessHandler {
@Override
public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) {
return Mono.defer(() -> Mono.just(webFilterExchange.getExchange().getResponse()).flatMap(response -> {
DataBufferFactory dataBufferFactory = response.bufferFactory();
DataBuffer dataBuffer = dataBufferFactory.wrap("登录成功".getBytes());
return response.writeWith(Mono.just(dataBuffer));
}));
}
}
复制代码
自定义登录失败处置惩罚器
@Component
public class LoginFailHandler implements ServerAuthenticationFailureHandler {
@Override
public Mono<Void> onAuthenticationFailure(WebFilterExchange webFilterExchange, AuthenticationException exception) {
return Mono.defer(() -> Mono.just(webFilterExchange.getExchange().getResponse()).flatMap(response -> {
DataBufferFactory dataBufferFactory = response.bufferFactory();
DataBuffer dataBuffer = dataBufferFactory.wrap("登录失败".getBytes());
return response.writeWith(Mono.just(dataBuffer));
}));
}
}
复制代码
自定义注销乐成处置惩罚器
@Component
public class LogoutSuccessHandler implements ServerLogoutSuccessHandler {
@Override
public Mono<Void> onLogoutSuccess(WebFilterExchange exchange, Authentication authentication) {
return Mono.defer(() -> Mono.just(exchange.getExchange().getResponse()).flatMap(response -> {
DataBufferFactory dataBufferFactory = response.bufferFactory();
DataBuffer dataBuffer = dataBufferFactory.wrap("logout success".getBytes());
return response.writeWith(Mono.just(dataBuffer));
}));
}
}
复制代码
@EnableWebFluxSecurity
@Configuration
public class SecurityConfig {
@Resource
private LoginSuccessHandler loginSuccessHandler;
@Resource
private LoginFailHandler loginFailHandler;
@Resource
private LogoutSuccessHandler logoutSuccessHandler;
@Bean
public SecurityWebFilterChain filterChain(ServerHttpSecurity http) {
http.httpBasic()
.and()
.authorizeExchange()
.anyExchange()
.authenticated();
http.formLogin()
.authenticationSuccessHandler(loginSuccessHandler)
.authenticationFailureHandler(loginFailHandler)
.and()
.logout()
.logoutSuccessHandler(logoutSuccessHandler);
return http.build();
}
/**
* 内存管理用户信息
*/
@Bean
public MapReactiveUserDetailsService userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new MapReactiveUserDetailsService(user);
}
}
复制代码
自定义用户信息
仿照 MapReactiveUserDetailsService 编写获取用户认证类
@Component
public class UserDetailService implements ReactiveUserDetailsService, ReactiveUserDetailsPasswordService {
private final Map<String, UserDetails> users = new HashMap<>();
@Resource
private PasswordEncoder passwordEncoder;
@Override
public Mono<UserDetails> findByUsername(String username) {
User user = null;
if ("user".equals(username)) {
user = new User("user", passwordEncoder.encode("123456"), true, true, true, true, new ArrayList<>());
}
return Mono.justOrEmpty(user);
}
@Override
public Mono<UserDetails> updatePassword(UserDetails user, String newPassword) {
return Mono.just(user)
.map(u ->
User.withUserDetails(u)
.password(newPassword)
.build()
)
.doOnNext(u -> {
this.users.put(user.getUsername().toLowerCase(), u);
});
}
}
复制代码
仿照 AbstractUserDetailsReactiveAuthenticationManager 编写用户认证管理类
@Component
public class UserAuthenticationManager extends AbstractUserDetailsReactiveAuthenticationManager {
@Resource
private PasswordEncoder passwordEncoder;
@Resource
private ReactiveUserDetailsService userDetailService;
@Resource
private ReactiveUserDetailsPasswordService userDetailsPswService;
private Scheduler scheduler = Schedulers.boundedElastic();
private UserDetailsChecker preAuthenticationChecks = user -> {
if (!user.isAccountNonLocked()) {
logger.debug("User account is locked");
throw new LockedException(this.messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.locked",
"User account is locked"));
}
if (!user.isEnabled()) {
logger.debug("User account is disabled");
throw new DisabledException(this.messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.disabled",
"User is disabled"));
}
if (!user.isAccountNonExpired()) {
logger.debug("User account is expired");
throw new AccountExpiredException(this.messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.expired",
"User account has expired"));
}
};
private UserDetailsChecker postAuthenticationChecks = user -> {
if (!user.isCredentialsNonExpired()) {
logger.debug("User account credentials have expired");
throw new CredentialsExpiredException(this.messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.credentialsExpired",
"User credentials have expired"));
}
};
@Override
public Mono<Authentication> authenticate(Authentication authentication) {
final String username = authentication.getName();
final String presentedPassword = (String) authentication.getCredentials();
return retrieveUser(username)
.doOnNext(this.preAuthenticationChecks::check)
.publishOn(this.scheduler)
.filter(u -> this.passwordEncoder.matches(presentedPassword, u.getPassword()))
.switchIfEmpty(Mono.defer(() -> Mono.error(new BadCredentialsException("Invalid Credentials"))))
.flatMap(u -> {
boolean upgradeEncoding = this.userDetailsPswService != null
&& this.passwordEncoder.upgradeEncoding(u.getPassword());
if (upgradeEncoding) {
String newPassword = this.passwordEncoder.encode(presentedPassword);
return this.userDetailsPswService.updatePassword(u, newPassword);
}
return Mono.just(u);
})
.doOnNext(this.postAuthenticationChecks::check)
.map(u -> new UsernamePasswordAuthenticationToken(u, u.getPassword(), u.getAuthorities()) );
}
@Override
protected Mono<UserDetails> retrieveUser(String username) {
return userDetailService.findBysername(username);
}
}
复制代码
@EnableWebFluxSecurity
@Configuration
public class SecurityConfig {
@Resource
private LoginSuccessHandler loginSuccessHandler;
@Resource
private LoginFailHandler loginFailHandler;
@Resource
private LogoutSuccessHandler logoutSuccessHandler;
@Resource
private UserAuthenticationManager userAuthenticationManager;
@Bean
public SecurityWebFilterChain filterChain(ServerHttpSecurity http) {
http.httpBasic()
.and()
.authorizeExchange()
.anyExchange()
.authenticated();
http.formLogin()
.authenticationManager(authenticationManager())
.authenticationSuccessHandler(loginSuccessHandler)
.authenticationFailureHandler(loginFailHandler)
.and()
.logout()
.logoutSuccessHandler(logoutSuccessHandler);
return http.build();
}
/**
* 注册用户信息验证管理器,可按需求添加多个按顺序执行
*/
@Bean
public ReactiveAuthenticationManager authenticationManager() {
LinkedList<ReactiveAuthenticationManager> managers = new LinkedList<>();
managers.add(userAuthenticationManager);
return new DelegatingReactiveAuthenticationManager(managers);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
复制代码
权限注解
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
@Configuration
public class SecurityConfig {
// ....
}
复制代码
@RestController
public class TestController {
/**
* 无效
*/
@Secured({"ROLE_ADMIN"})
@RequestMapping(value = "/test")
public Mono<String> test() {
return Mono.just("test");
}
/**
* 有效
*/
@PreAuthorize("hasRole('ADMIN')")
@RequestMapping(value = "/test1")
public Mono<String> test1() {
return Mono.just("test1");
}
@Secured({"ROLE_TEST"})
@RequestMapping(value = "/test2")
public Mono<String> test2() {
return Mono.just("test2");
}
}
复制代码
自定义权限处置惩罚器
@Component
public class AccessDeniedHandler implements ServerAccessDeniedHandler {
@Override
public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied) {
return Mono.defer(() -> Mono.just(exchange.getResponse()).flatMap(response -> {
DataBufferFactory dataBufferFactory = response.bufferFactory();
DataBuffer dataBuffer = dataBufferFactory.wrap("permission denied".getBytes());
return response.writeWith(Mono.just(dataBuffer));
}));
}
}
复制代码
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
@Configuration
public class SecurityConfig {
@Resource
private LoginSuccessHandler loginSuccessHandler;
@Resource
private LoginFailHandler loginFailHandler;
@Resource
private LogoutSuccessHandler logoutSuccessHandler;
@Resource
private UserAuthenticationManager userAuthenticationManager;
@Resource
private AccessDeniedHandler accessDeniedHandler;
@Bean
public SecurityWebFilterChain filterChain(ServerHttpSecurity http) {
http.httpBasic()
.and()
.authorizeExchange()
.anyExchange()
.authenticated();
http.formLogin()
.authenticationManager(authenticationManager())
.authenticationSuccessHandler(loginSuccessHandler)
.authenticationFailureHandler(loginFailHandler)
.and()
.logout()
.logoutSuccessHandler(logoutSuccessHandler)
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler);
return http.build();
}
/**
* 注册用户信息验证管理器,可按需求添加多个按顺序执行
*/
@Bean
public ReactiveAuthenticationManager authenticationManager() {
LinkedList<ReactiveAuthenticationManager> managers = new LinkedList<>();
managers.add(userAuthenticationManager);
return new DelegatingReactiveAuthenticationManager(managers);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
复制代码
自定义认证处置惩罚器
@Component
public class AuthenticationEntryPoint implements ServerAuthenticationEntryPoint {
@Override
public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException e) {
return Mono.defer(() -> Mono.just(exchange.getResponse()).flatMap(response -> {
DataBufferFactory dataBufferFactory = response.bufferFactory();
DataBuffer dataBuffer = dataBufferFactory.wrap("Authentication fail".getBytes());
return response.writeWith(Mono.just(dataBuffer));
}));
}
}
复制代码
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
@Configuration
public class SecurityConfig {
@Resource
private LoginSuccessHandler loginSuccessHandler;
@Resource
private LoginFailHandler loginFailHandler;
@Resource
private LogoutSuccessHandler logoutSuccessHandler;
@Resource
private UserAuthenticationManager userAuthenticationManager;
@Resource
private AccessDeniedHandler accessDeniedHandler;
@Resource
private AuthenticationEntryPoint authenticationEntryPoint;
@Bean
public SecurityWebFilterChain filterChain(ServerHttpSecurity http) {
http.httpBasic()
.and()
.authorizeExchange()
.anyExchange()
.authenticated();
http.formLogin()
.authenticationManager(authenticationManager())
.authenticationSuccessHandler(loginSuccessHandler)
.authenticationFailureHandler(loginFailHandler)
.and()
.logout()
.logoutSuccessHandler(logoutSuccessHandler)
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
.authenticationEntryPoint(authenticationEntryPoint);
return http.build();
}
/**
* 注册用户信息验证管理器,可按需求添加多个按顺序执行
*/
@Bean
public ReactiveAuthenticationManager authenticationManager() {
LinkedList<ReactiveAuthenticationManager> managers = new LinkedList<>();
managers.add(userAuthenticationManager);
return new DelegatingReactiveAuthenticationManager(managers);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
复制代码
自定义鉴权处置惩罚器
[code]@Slf4j@Componentpublic class AuthorizeConfigManager implements ReactiveAuthorizationManager { private final AntPathMatcher antPathMatcher = new AntPathMatcher(); @Override public Mono check(Mono authentication, AuthorizationContext authorizationContext) { return authentication.map(auth -> { ServerWebExchange exchange = authorizationContext.getExchange(); ServerHttpRequest request = exchange.getRequest(); Collection
欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/)
Powered by Discuz! X3.4