У меня мультитенантная среда, одна база данных с отдельной схемой для каждого арендатора.
При входе в систему я загружаю клиента по умолчанию, и все работает отлично. Я создаю метод switchTenant, который должен переключать текущего арендатора (по умолчанию) с выбранным. У меня есть частично рабочее решение, где я сохраняю эту информацию в HttpSession. Все работает, с некоторыми побочными эффектами, такими как: при перезапуске tomcat пользователи должны повторно войти в систему, или пользователи андроида при закрытии приложения теряют свой сеанс.
Пытался найти лучшее решение для замены HttpSession хранением текущей информации об арендаторе в SecurityContext. И, конечно, я потерпел неудачу, поэтому я прошу вас о помощи.
Вот соответствующий код, который я пытаюсь заставить работать:
TenantInterceptor (здесь все в порядке)
...
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) {
String schema = SecurityUtils.getCurrentSchema().orElse("");
if (schema.equals("")) {
TenantContext.setCurrentTenant("public");
} else {
TenantContext.setCurrentTenant(schema);
}
return true;
}
...
Класс помощника SecurityUtils (и здесь все в порядке)
...
public static Optional<String> getCurrentSchema() {
SecurityContext securityContext = SecurityContextHolder.getContext();
return Optional.ofNullable(securityContext.getAuthentication()).map(authentication -> {
if (authentication.getPrincipal() instanceof TenantUser) {
TenantUser springSecurityUser = (TenantUser) authentication.getPrincipal();
return springSecurityUser.getCurrentSchema();
}
return null;
});
}
...
Класс обслуживания (который мне нужно исправить)
...
public void switchTenant(Tenant tenant) {
Optional<TenantDTO> tenantExist = this.findAllUserTenants().stream()
.filter(t -> t.getName().equals(tenant.getName())).findFirst();
if (tenantExist.isPresent()) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
Authentication newAuth = null;
if (auth.getClass() == UsernamePasswordAuthenticationToken.class) {
TenantUser principal = (TenantUser) auth.getPrincipal();
principal.setCurrentSchema(tenant.getSchema());
newAuth = new UsernamePasswordAuthenticationToken(principal, auth.getCredentials(), auth.getAuthorities());
}
SecurityContextHolder.getContext().setAuthentication(newAuth);
...
Класс TenantUser
public class TenantUser extends org.springframework.security.core.userdetails.User {
private String userId;
private String currentSchema;
public TenantUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
...
Неважно, что, эта строка кода: SecurityContextHolder.getContext (). SetAuthentication (newAuth); всегда дает мне старую аутентификацию, а не ту, с обновленной текущей схемой арендатора
Спасибо за помощь.