Spring Security 中的“主体”是什么?

新手上路,请多包涵

我真的是 Spring 和 Spring Security 的新手。我正在阅读有关 Spring Security 的文章,它提出了 principal 的概念,它应该是当前登录的用户。但是,如果我们有多个当前登录用户怎么办?所以,我的问题是,spring security 的主体到底是什么?

例如,我读过本教程:

http://www.mkyong.com/spring-security/get-current-logged-in-username-in-spring-security/

而且他们似乎考虑到当前只有一个登录用户,但这种情况并不常见。

如何检索特定用户?我如何区分发出请求的用户?

原文由 nbro 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 312
2 个回答

主体 当前登录的用户。但是,您通过绑定到当前线程的安全上下文检索它,因此它也绑定到当前请求及其会话。

SecurityContextHolder.getContext() 内部获取当前 SecurityContext 实现通过 ThreadLocal 变量。因为请求绑定到单个线程,所以这将为您提供当前请求的上下文。

为简化起见,您可以说安全上下文在会话中并且包含用户/主体和角色/权限。

如何检索特定用户?

你不知道。所有 API 都旨在允许访问当前请求的用户和会话。让用户 A 成为 100 个当前经过身份验证的用户之一。如果 A 向您的服务器发出请求,它将分配一个线程来处理该请求。如果您随后执行 SecurityContextHolder.getContext().getAuthentication() 您将在此线程的上下文中执行此操作。默认情况下,您无法从该线程中访问由不同线程处理的用户 B 的上下文。

我如何区分发出请求的用户?

您不必这样做,这就是 Servlet 容器为您所做的。

原文由 Marcel Stör 发布,翻译遵循 CC BY-SA 3.0 许可协议

Principal 只是 Java SE 6 的一个旧接口。

由于没有默认实现的所有接口, 它简单定义了一些方法 ,这些方法需要由将实现该接口的类实现

这些方法是

boolean  equals(Object another)
          Compares this principal to the specified object.

String   getName()
          Returns the name of this principal.

int      hashCode()
          Returns a hashcode for this principal.

String   toString()
          Returns a string representation of this principal.

正如 Java 文档 所述:

该接口代表主体的抽象概念, 可以用来代表任何实体,例如个人、公司和登录 id

简单来说,它只是用来让实现者必须以一种使实体在其他实体之间具有唯一区别的方式来实现此接口。此外 getName() 将必须返回一个值,通过该值可以唯一标识一个特定实体并且不会与其他实体发生冲突。 So if the Principal which is used is of type UserDetails then the getName() of Principal returns the UserName of UserDetails

如果我们看到 Spring 用于 AbstractAuthenticationToken.class 的实现:

 public String getName() {
        if (this.getPrincipal() instanceof UserDetails) {
            return ((UserDetails)this.getPrincipal()).getUsername();
        } else if (this.getPrincipal() instanceof AuthenticatedPrincipal) {
            return ((AuthenticatedPrincipal)this.getPrincipal()).getName();
        } else if (this.getPrincipal() instanceof Principal) {
            return ((Principal)this.getPrincipal()).getName();
        } else {
            return this.getPrincipal() == null ? "" : this.getPrincipal().toString();
        }
    }

还有一点很重要:

abstract class AbstractAuthenticationToken implements Authentication

interface Authentication extends Principal

Principal 接口还确保实施者将实施 equals()hashCode() 这很有意义,因为委托人或实体必须代表公司或实体有某种方式与其他实体进行比较。

原文由 Panagiotis Bougioukos 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题