Я использую Spring Webflux, и после реализации ReactiveAuthenticationManager следующая задача - сохранить сеанс в redis.
Вместо случайного создания идентификатора сеанса (ключей redis) из UUID, я хочу выбрать заголовок имени пользователя из запросазаголовки и установите его как мой sessionId для сохранения в redis.
Причина: мои клиенты уже прошли проверку подлинности через стороннюю службу, и я только хочу проверять их предоставленные полномочия из redis (вместо проверки из базы данных каждый раз).).В запросе нет файла cookie с идентификатором sessionId, а также я хочу, чтобы сеансы отображались в заголовок userName вместо идентификатора сеанса, генерируемого весной (случайные UUID).
Что я пробовал:
Я пыталсяизменение Websession путем получения ServerWebExchange в Webfilter , а также в ServerSecurityContextRepository load метод, но ServerWebExchange здесь не позволяет мне изменить sessionId на фиксированное значение (или некоторую логику генерации)
Фрагменты кода:
@Component
public class SecurityContextRepository implements ServerSecurityContextRepository {
private final DaoAuthenticationManager authenticationManager;
@Autowired
public SecurityContextRepository(DaoAuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Mono<Void> save(ServerWebExchange swe, SecurityContext sc) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Mono<SecurityContext> load(ServerWebExchange swe) {
ServerHttpRequest request = swe.getRequest();
if (request.getHeaders().containsKey("userName") &&
!Objects.requireNonNull(request.getHeaders().get("userName")).isEmpty()) {
String userName = Objects.requireNonNull(swe
.getRequest()
.getHeaders()
.get("userName")).get(0);
Authentication auth = new UsernamePasswordAuthenticationToken(userName,
Security.PASSWORD);
return this.authenticationManager.authenticate(auth).map(SecurityContextImpl::new);
} else {
return Mono.empty();
}
}
}
@Component
public class DaoAuthenticationManager implements ReactiveAuthenticationManager {
private final DaoUserDetailsService userDetailsService;
private final Scheduler scheduler;
@Autowired
public DaoAuthenticationManager(DaoUserDetailsService userDetailsService,
Scheduler scheduler) {
Assert.notNull(userDetailsService, "userDetailsService cannot be null");
this.userDetailsService = userDetailsService;
this.scheduler = scheduler;
}
@Override
public Mono<Authentication> authenticate(Authentication authentication) {
final String username = authentication.getName();
return this.userDetailsService.findByUsername(username)
.publishOn(this.scheduler)
.switchIfEmpty(
Mono.defer(() -> Mono.error(new
UsernameNotFoundException("Invalid Username"))))
.map(u -> new UsernamePasswordAuthenticationToken(u, u.getPassword(),
u.getAuthorities()));
}
}
@Configuration
@EnableRedisWebSession(redisNamespace = Constants.DEFAULT_SESSION_NAMESPACE, maxInactiveIntervalInSeconds = Constants.SESSION_LIFECYCLE)
public class RedisConfig {
}
UserDetailsService основан на UserRepository, который выбирает роли для пользователя из реляционной таблицы.
- Любые указатели на то, как мутировать sessionExchange, чтобы установить sessionId на userId
- Я хочу изменитьЗагрузите метод, чтобы сначала получить роли из сеанса, а затем проверить проверку из JDBC и вернуть в Redis.
Другие лучшие практики или подходы для ее решения:Добро пожаловать.