【问题标题】:Spring Security, updating SecurityContextHolderSpring Security,更新 SecurityContextHolder
【发布时间】:2019-09-08 22:42:28
【问题描述】:

我有多租户环境,一个数据库,每个租户都有单独的架构。

在用户登录时,我加载了默认租户,一切正常。我创建了 switchTenant 方法,该方法应该将当前租户(默认一个)与选定的租户切换。我有部分工作解决方案,我将这些信息保存在 HttpSession 中。一切正常,但有一些副作用,例如:在 tomcat 重启时用户需要重新登录,或者应用程序关闭时的 android 用户会丢失会话。

试图找到更好的解决方案来替换 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); 总是让我得到旧的身份验证,而不是更新当前租户架构的身份

感谢您的帮助。

【问题讨论】:

    标签: spring spring-security multi-tenant


    【解决方案1】:

    方法很糟糕。因为我使用 jwt 令牌进行身份验证,所以最好的方法是将当前租户模式存储到令牌中。 在租户切换时,我确实使用新的当前架构刷新了令牌并将其发送回客户端。

    【讨论】:

      猜你喜欢
      • 2015-02-08
      • 1970-01-01
      • 2011-03-28
      • 2011-09-18
      • 1970-01-01
      • 1970-01-01
      • 2016-03-02
      • 2015-05-16
      • 2012-08-31
      相关资源
      最近更新 更多