java - 带嵌套帐户的 Spring Security

标签 java spring spring-security

我在 Spring Security 中授权嵌套帐户时遇到困难。我是 Spring Security 的新手。我花了大约一周的时间才找到一个可行的解决方案,但它是一个丑陋的解决方案,我很想重构它......

我正在使用 Spring 4.2.4 和 Spring Security 4.0.3。

我的用户帐户如下所示:

Office用户A

Office用户B

现场用户C

--> 字段子用户 a

--> 字段子用户 b

现场用户D

--> 字段子用户 c

因此,办公室用户只有一个帐户,但现场用户始终至少有一个子帐户,并且可能有两个或更多子帐户。每个子账户可以有不同的权限。就像一个子账户只能查看,另一个子账户可以查看和创建。

用户将使用帐户(A、B、C 或 D)登录。如果 A 或 B 登录,则没有问题。但是,如果用户 C 登录,他们需要选择(a 或 b),我们需要他们的选择信息。如果用户 D 登录,我们需要用户 (c) 的信息。我正在使用 Spring Security 并努力获取上面的用户 a/b/c 的信息。我找到了一个解决方案,但并不理想,我想知道更合适的方法。

我的解决方案:

在 UserDetails 的 @AuthenticationPrincipal 实现中,添加以下代码:

private Collection<GrantedAuthority> authorities;
private String uniqueId1;
private String uniqueId2;
public void setAuthorities(Collection<GrantedAuthority> authorities) {
    this.authorities = authorities;
}

public Collection<GrantedAuthority> getAuthorities() {
    if (this.authorities != null) {
        return this.authorities; //CHILD
    }
    return super.getAuthorities(); // (SUPER)
}
public void setUniqueId1(String uniqueId1) {
    this.uniqueId1 = uniqueId1;
}

public String getUniqueId1() {
    if (this.uniqueId1!= null) {
        return this.uniqueId1; //CHILD
    }
    return super.getUniqueId1(); // (SUPER)
}
public void setUniqueId2(String uniqueId2) {
    this.uniqueId2 = uniqueId2;
}

public String getUniqueId2() {
    if (this.uniqueId2!= null) {
        return this.uniqueId2; //CHILD
    }
    return super.getUniqueId2(); // (SUPER)
}

然后,在我获取登录用户信息的方法中,接受所选用户的字符串并执行以下操作:

public @ResponseBody FullUserDetails getLoggedInUserInfo(
            @AuthenticationPrincipal MyImplementationOfUserDetails user,
            String selectedUsername)

MyImplementationOfUserDetails user2 = getUserInfo(selectedUsername);

user.setAuthorities(user2.getAuthorities());
user.setUniqueId1(user2.getUniqueId1());
user.setUniqueId2(user2.getUniqueId2());

通过这种方式,我能够“更改”权限和唯一 id 属性,否则这些属性是不可更改的,因为它们在父类中是私有(private)的,并且通常只能通过构造函数访问。 我尝试在 UserDetails 实现中创建一个新的构造函数,但是当我创建一个新的 @AuthenticationPrincipal 时,它不会覆盖 session 中的构造函数。我认为需要一个新的构造函数将是最正确的方法。如何使用新的 UserDetails 对象覆盖 session 中的 @AuthenticationPrincipal?或者是否有一种我没有想到的更好的方法?我只想将所选子用户新权限和唯一ID信息放入@AuthenticationPrincipal中。下次我获取 @AuthenticationPrincipal 时,它将包含该信息。

不获取新信息并将其放入@AuthenticationPrincipal的后果是网页行为将是错误的。主要是因为所选用户的权限级别不正确。

我试图打电话:

SecurityContextHolder.getContext().setAuthentication(newAuthenticationObjectHere);

但是调用 setAuthentication() 后我没有看到变化...

我能够看到更改的唯一方法是直接调用从 @AuthenticationPrinciple 检索的 MyImplementationOfUserDetails 对象中的 setter 。

最佳答案

抱歉,很困惑,但主要思想几乎可以理解。

我认为您会不断地想出一个想法来计算帐户之间的所有复杂关系,然后为最终帐户提供所需的权限并提供对某些资源的访问权限。

如果要更改提供资源访问权限而不操纵帐户关系的逻辑会怎样?还有一个非常重要的链 - 使用像 Spring OAuth2 这样的远程/分布式授权服务器?有了它,您可以拥有任何帐户和范围的权限(!)。根据组织条件,帐户可以具有不同的范围。您的最终资源(通常是 Controller 方法)已按范围进行预身份验证。按照这个思路,可以将基于账户具体提供访问的逻辑分开,用账户来实现DB中的所有逻辑。

也许这对您的项目来说是错误的想法,但对我来说它是有效的 - 我根据客户的条件更改客户的范围,但不会在运行时操纵他们的数据和关系。

关于java - 带嵌套帐户的 Spring Security,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59491062/

相关文章:

java - spring 设置 2 个调度程序 servlet 和安全性

java - 我们可以将输入的用户名传递给 spring security 中的身份验证失败 url 吗?

spring - STOMP over websockets 与普通 STOMP。哪一个更好?

java - Travis CI Spring Boot 错误(Gradle 错误)

java - 浏览器特定的 session 管理

java - 在现有数据库中创建表 sqlite sugar orm

java - Springboot 与 Spring OAuth2

java - 如何在 LinkedList 实现中的指定索引处添加节点

java - JTable - 在多个单元格中换行文本

java - AWS Athena ClientExecutionTimeoutException