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 访问模板进行验证。
备注:内容仅供参考。
