PAYATHON 2026

Thymeleaf 的 sec:authentication 为什么不显示登录信息?

数据小许

结论

日志显示,这次请求成功获取了登录用户的 SecurityContext,用户名为 snl,权限为 ROLE_USER。接下来应检查 Thymeleaf 的安全扩展、属性表达式和模板渲染路径。

模板中的 Principal.Username 和 Principal.authorities 需要按属性名称的大小写修正。显示用户名和权限时,可以直接使用:

<div>
  当前登录用户:<b sec:authentication="name"></b>
  权限:<span sec:authentication="authorities"></span>
</div>

Spring Boot 3.3.x 的标准依赖组合使用 Spring Security 6,需要对应的 thymeleaf-extras-springsecurity6 扩展。问题没有提供依赖文件和 Controller,目前无法判断是否还存在扩展缺失或模板未被处理的情况。

为什么认证成功,页面仍然没有内容?

原始日志中有以下信息:

Authenticated=true
Granted Authorities=[ROLE_USER]

这说明 Spring Security 已建立认证信息。要把这些信息写入 HTML,还需要 Thymeleaf 在服务端处理 sec:authentication。

sec:authentication 是模板属性,浏览器不会执行它。如果服务端没有处理,下面的元素就没有可显示的文本:

<b sec:authentication="Principal.Username"></b>

日志里的 Principal= 和 Username= 是对象的日志展示格式,不能直接当作模板属性路径。属性访问需要使用正确的名称,例如 principal.username。

1. 检查 Spring Security 对应的 Thymeleaf 扩展

如果项目使用 Maven,并通过 Spring Boot 3.3.x 的 parent 或 BOM 管理依赖版本,可以检查是否包含:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity6</artifactId>
</dependency>

这里使用的是 springsecurity6。如果项目没有使用 Spring Boot 的依赖管理,需要自行指定与现有依赖兼容的版本,不能直接照搬省略版本号的配置。

模板中的命名空间可以保留:

xmlns:sec="http://www.thymeleaf.org/extras/spring-security"

声明 xmlns:sec 不会自动安装或启用扩展,还需要相应依赖和方言配置。

2. 修正模板中的属性表达式

可以使用下面的完整模板进行验证:

<!DOCTYPE html>
<html lang="zh"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
  <meta charset="UTF-8">
  <title>登录信息</title>
</head>
<body>
  <div sec:authorize="isAuthenticated()">
    当前登录用户:<b sec:authentication="name"></b>
    权限:<span sec:authentication="authorities"></span>
  </div>
</body>
</html>

name 对应当前 Authentication 的名称,authorities 对应权限集合。

对于问题中使用的 org.springframework.security.core.userdetails.User,也可以通过 principal 读取用户名:

<b sec:authentication="principal.username"></b>

principal 和 username 都以小写字母开头。principal.username 依赖实际 principal 对象提供相应属性,当前问题中的 User 满足这一条件。

配置中的 .roles("USER") 会生成 ROLE_USER,因此权限输出中出现 ROLE_USER 是正常的。

3. 确认页面经过 Thymeleaf 渲染

在 Spring Boot 默认配置下,可以将模板保存为:

src/main/resources/templates/login-info.html

然后通过返回视图名称的 Controller 访问它,例如:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class LoginInfoController {

    @GetMapping("/login-info")
    public String loginInfo() {
        return "login-info";
    }
}

登录后访问 /login-info。这里使用 @Controller,方法返回值用于解析模板;如果使用 @RestController 或 @ResponseBody,该字符串会作为响应正文返回。

如果 HTML 放在默认的 static 目录下作为静态资源提供,或者直接从本地打开文件,sec:authentication 不会执行。

可以临时加入一个普通 Thymeleaf 表达式:

<p th:text="'Thymeleaf 已执行'">模板尚未处理</p>

结合服务端返回的 HTML 判断:

  • 仍显示“模板尚未处理”:优先检查视图解析和模板访问方式。
  • 显示“Thymeleaf 已执行”,但 sec:authentication 属性仍原样保留:检查安全扩展是否加载到当前模板引擎。
  • 出现模板求值异常:查看异常中的属性路径,确认已经修正 Principal.Username 等表达式。

这些现象可以帮助缩小排查范围,不能仅凭某一种页面表现认定根因。

4. 自定义模板引擎时检查方言注册

在 Spring Boot 默认自动配置生效、对应扩展位于 classpath 的情况下,通常无需手工注册 SpringSecurityDialect。

如果项目自行创建了 SpringTemplateEngine,需要确认实际处理页面的引擎包含安全方言。例如,可以在构建该引擎时加入:

import org.thymeleaf.extras.springsecurity6.dialect.SpringSecurityDialect;

// templateEngine 为实际用于处理页面的 SpringTemplateEngine
// 在模板引擎初始化和使用前注册
 templateEngine.addDialect(new SpringSecurityDialect());

原问题没有提供自定义模板引擎配置,因此这一步只适用于自行接管 Thymeleaf 配置的项目。优先检查扩展依赖并修正属性大小写,再通过 Controller 访问模板进行验证。

备注:内容仅供参考。