1. 概述

安全性是任何 Java 应用程序中不可或缺的一部分。市面上有很多安全框架可以帮我们处理认证、授权等安全问题。同时,在这些框架中,我们也会频繁遇到一些术语,比如 Subject(主体)Principal(身份)User(用户)

本篇文章将为你梳理这些安全框架中的基本概念,解释它们之间的关系和区别,帮助你在设计和实现安全逻辑时更加得心应手。

2. Subject(主体)

在安全上下文中,Subject 代表请求的来源。简单来说,它是一个可以访问资源、获取信息或修改资源的实体。

✅ Subject 可以是:

  • 一个用户
  • 一个程序
  • 一个进程
  • 一个文件
  • 一台计算机
  • 一个数据库
    ...等等

举个例子:当一个人需要访问某个资源时,他必须先进行身份认证,以证明他是请求的合法来源。在这个场景下,这个人就是一个 Subject。

下面是一个基于 JAAS 的代码示例:

Subject subject = loginContext.getSubject();
PrivilegedAction privilegedAction = new ResourceAction();
Subject.doAsPrivileged(subject, privilegedAction, null);

这段代码的作用是:使用认证后的 Subject 执行一个特权操作。

3. Principal(身份)

认证成功后,Subject 会携带多个身份信息(Principal),比如角色、社保号、用户名等。这些身份信息就是 Principal

举个例子:一个人可能拥有一个账户号 Principal(比如 “87654-3210”)和其他唯一标识符,用来把他和其他 Subject 区分开。

下面是一个登录成功后创建 UserPrincipal 并添加到 Subject 的示例:

@Override
public boolean commit() throws LoginException {
    if (!loginSucceeded) {
        return false;
    }
    userPrincipal = new UserPrincipal(username);
    subject.getPrincipals().add(userPrincipal);
    return true;
}

这段代码属于 JAAS 的 LoginModule,认证成功后会把用户身份添加到 Subject 中。

4. User(用户)

User 通常表示一个访问资源的人,可能是执行某个任务的终端用户,也可能是后台的操作员。

⚠️ 注意:User 本身也可以被当作一个 Principal 来使用。换句话说,Principal 是赋予 User 的身份标识。

在 JAAS 中,UserPrincipal 就是一个典型的例子:

UserPrincipal userPrincipal = new UserPrincipal("john_doe");

它代表的是一个具体的用户身份,绑定在 Subject 上。

5. Subject、Principal 和 User 的区别

这三者之间的关系可以用一句话总结:

User 是 Principal 的一种,而 Principal 是 Subject 的一部分。

更具体地说:

概念 含义 类型
Subject 请求来源的实体 最外层容器
Principal 身份标识(角色、用户名等) Subject 的属性
User 代表一个具体用户 Principal 的一种

✅ 举个通俗的例子:

  • Subject:一台电脑
  • Principal:用户名、角色、部门编号
  • User:张三

6. 总结

本文讲解了安全框架中常见的三个核心概念:Subject、Principal 和 User,并通过代码示例展示了它们的使用方式和相互关系。

这些概念在 Spring Security、Shiro、JAAS 等框架中都有体现,掌握它们有助于你更深入地理解和设计系统安全机制。

所有示例代码均可在 GitHub 项目 中找到。


原始标题:Security Context Basics: User, Subject and Principal | Baeldung