java - Spring WebFlux 中的 SecurityContext 始终为空
问题描述
我用 JWT 配置了 Spring Webflux。创建自定义ServerSecurityContextRepository
并将其添加到SecurityWebFilterChain
. 但是当我在传入请求时获得 SecurityContext 时, Security context 总是返回null
。
以下代码是我的配置:
SecurityContextRepository.class
@Component
public class SecurityContextRepository implements ServerSecurityContextRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(SecurityContextRepository.class);
private static final Pattern PATTERN = Pattern.compile("Bearer (.+)");
private final JWTVerifier verifier;
private final UserRepository userRepository;
@SuppressFBWarnings("EXS_EXCEPTION_SOFTENING_NO_CONSTRAINTS")
public SecurityContextRepository(
SignatureAlgorithmProvider algorithmProvider, UserRepository userRepository) {
this.userRepository = requireNonNull(userRepository);
try {
verifier = JWT.require(algorithmProvider.algorithm()).withIssuer(JwtTokenGenerator.ISSUER).build();
} catch (Exception e) {
throw new BeanInitializationException("Could not initialize JWT verifier", e);
}
}
@Override
public Mono<Void> save(ServerWebExchange serverWebExchange, SecurityContext securityContext) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Mono<SecurityContext> load(ServerWebExchange serverWebExchange) {
var token = extractToken(serverWebExchange.getRequest());
if (token == null) {
return Mono.empty();
} else {
try {
var jwt = verifier.verify(token);
var userId = UUID.fromString(jwt.getSubject());
var userOptional = userRepository.fetchOneById(userId);
if (userOptional.isPresent()) {
var user = userOptional.get();
return Mono.just(new SecurityContextImpl(new JwtAuthenticationToken(securityUser, roles(user.roles()))));
}
return Mono.empty();
} catch (JWTDecodeException | IllegalArgumentException e) {
LOGGER.warn("Bearer token cannot be decoded as JWT: {}", token, e);
return Mono.error(new UnauthorizedException("Bearer token cannot be decoded as JWT.", e));
} catch (SignatureVerificationException e) {
LOGGER.warn("Received access token with an invalid signature: {}", token, e);
return Mono.error(
new UnauthorizedException("Received access token with an invalid signature.", e));
} catch (TokenExpiredException e) {
LOGGER.warn("JWT token expired.", e);
return Mono.error(new UnauthorizedException("JWT token expired.", e));
} catch (Exception e) {
LOGGER.warn("Exception verifying JWT: {}", token, e);
return Mono.error(new UnauthorizedException("Exception verifying JWT.", e));
}
}
}
}
安全配置类
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfiguration {
private final SecurityContextRepository securityContextRepository;
@Autowired
public SecurityConfiguration(SecurityContextRepository securityContextRepository) {
this.securityContextRepository = requireNonNull(securityContextRepository);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@SuppressFBWarnings(value = "SPRING_CSRF_PROTECTION_DISABLED")
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
// Disable default security.
return http.httpBasic()
.disable()
.formLogin()
.disable()
.csrf()
.disable()
.logout()
.disable()
.cors()
.and()
// Add custom security.
.securityContextRepository(securityContextRepository)
.addFilterAt(
new SecurityContextServerWebExchangeWebFilter(),
SecurityWebFiltersOrder.SECURITY_CONTEXT_SERVER_WEB_EXCHANGE)
.authorizeExchange()
.pathMatchers("/api/authentication/v1/*", "/status", "/info", "/health", "/docs/**")
.permitAll()
.pathMatchers(HttpMethod.GET, "/api/locations/v1/**")
.permitAll()
.anyExchange()
.authenticated()
.and()
.exceptionHandling()
.and()
.build();
}
}
Jwt 版本:com.auth0:java-jwt:3.10.3
SpringBoot 版本:2.3.2:RELEASE
解决方案
推荐阅读
- angular - 为什么在另一个中导入实体模块会破坏 Jhipster 中的功能
- groovy - 如何在 RestAssured body() 方法中参数化 groovy 语句
- chromium - debian 8 铬感染
- php - 我应该运行多少个 Docker 容器
- javascript - 从包含 4 个变量的表中获取结果?
- angular - Angular 7:div innerHTML 绑定在有或没有对位置 html 数据进行 html 清理的情况下都不起作用
- bash - 查找一组文件夹中的所有 HTML 文件,提取特定的 HTML 内容并将内容保存到新文件
- c - 当 unsigned int 可以保存任何地址时,uintptr_t 和 unsigned int 之间有什么区别吗?
- javascript - 异步/等待功能无法正常工作
- r - 使用 foreach 循环在数据框中创建新变量