You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中使用thymeleaf-extras-springsecurity的sec标签获取OIDC UserInfo遇问题

问题描述

在Spring Boot 3.3.5环境下,已引入thymeleaf-extras-springsecurity6依赖并声明xmlns:sec,使用sec:标签展示UserInfo字段时遇到异常:

  • 原生Thymeleaf写法可正常运行:
    <div th:text="${#authentication.getPrincipal().getUserInfo().getFullName()}"></div>
    
  • 但sec:authentication标签写法执行失败:
    <div sec:authentication="principal.userinfo.fullname"></div>
    

堆栈跟踪显示:sec:authentication.principal返回的是OAuth2AuthenticatedPrincipal实例,而#authentication.getPrincipal()返回的是DefaultOidcUser实例——后者自带getUserInfo()方法,前者没有。推测sec:authentication基于访问令牌处理,Thymeleaf原生方式基于ID令牌,想实现让sec:authentication获取ID令牌相关内容。

解决方案

方法1:SpEL表达式强制类型转换

直接在sec:authentication的表达式里把Principal强转为DefaultOidcUser,就能直接访问userInfo属性:

<div sec:authentication="T(org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser).cast(principal).userInfo.fullName"></div>

方法2:自定义Thymeleaf Spring Security表达式处理器

如果需要频繁使用该逻辑,可以自定义表达式处理器,让sec:标签默认识别DefaultOidcUser:

  1. 创建自定义解析器类:
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.thymeleaf.extras.springsecurity6.auth.AuthenticationObjectResolver;

public class OidcAuthenticationObjectResolver implements AuthenticationObjectResolver {
    @Override
    public Object resolvePrincipal(Authentication authentication) {
        Object principal = authentication.getPrincipal();
        if (principal instanceof DefaultOidcUser) {
            return principal;
        }
        return AuthenticationObjectResolver.super.resolvePrincipal(authentication);
    }
}
  1. 配置Thymeleaf替换默认处理器:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.extras.springsecurity6.dialect.SpringSecurityDialect;
import org.thymeleaf.extras.springsecurity6.auth.AuthenticationObjectResolver;

@Configuration
public class ThymeleafSecurityConfig {
    @Bean
    public SpringSecurityDialect springSecurityDialect() {
        SpringSecurityDialect dialect = new SpringSecurityDialect();
        dialect.setAuthenticationObjectResolver(new OidcAuthenticationObjectResolver());
        return dialect;
    }
}

配置完成后,原来的sec:authentication="principal.userinfo.fullname"写法即可正常运行。

方法3:调整Spring Security OIDC配置

确保Spring Security认证后将DefaultOidcUser作为Authentication的Principal保存,避免被包装为OAuth2AuthenticatedPrincipal。检查OIDC客户端配置,使用默认的OidcUserService即可:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;

@Configuration
public class OAuth2Config {
    @Bean
    public OidcUserService oidcUserService() {
        return new OidcUserService();
    }
}

内容的提问来源于stack exchange,提问作者Jeff E Mandel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 10:08:18