Spring Session: изменение логики генерации идентификатора сеанса с UUID на пользовательскую генерацию, скажем, с заголовков запросов - PullRequest
0 голосов
/ 26 января 2019

Я использую 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.

Другие лучшие практики или подходы для ее решения:Добро пожаловать.

...