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

Jhipster集成Azure AD(Entra ID) JWT认证遇401及Principal为空问题

解决方案:适配Azure AD(Entra ID)的Spring Security资源服务器配置

核心问题根源

你的项目初始基于Keycloak配置,切换到Azure AD后,SecurityFilterChain里的OAuth2资源服务器规则未同步调整,导致Azure AD颁发的JWT无法通过原有验证逻辑;移除oauth2ResourceServer配置后,Spring Security跳过了认证流程,自然无法获取到Principal信息。


1. 确认依赖配置

确保项目的依赖管理文件(Maven/Gradle)包含Spring Security OAuth2资源服务器核心依赖:

<!-- Maven pom.xml -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. 配置Azure AD参数

在application.yml中添加Azure AD租户和API的核心配置:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          # 替换为你的Azure AD租户ID
          issuer-uri: https://login.microsoftonline.com/your-tenant-id/v2.0
          # 可选:如果API在Azure AD中配置了自定义范围,需填写API的客户端ID
          audience: api://your-api-client-id

注:issuer-uri会让Spring自动拉取Azure AD的公钥和验证规则,无需手动配置密钥。

3. 构建正确的SecurityFilterChain

替换原有Keycloak相关配置,编写适配Azure AD的认证规则:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            // 前后端分离项目建议禁用CSRF(若前端已处理CSRF可保留)
            .csrf(csrf -> csrf.disable())
            // 配置接口授权规则,按需调整
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll() // 公开接口无需认证
                .anyRequest().authenticated() // 其他接口需Azure AD认证
            )
            // 配置OAuth2资源服务器,启用JWT验证
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(jwt -> jwt
                    // 可选:自定义JWT到Authentication的映射规则
                    .jwtAuthenticationConverter(customJwtConverter())
                )
            );
        return http.build();
    }

    // 可选:自定义JWT转换器,映射Azure AD的Claim到Spring Security权限/Principal
    /*
    @Bean
    public JwtAuthenticationConverter customJwtConverter() {
        JwtGrantedAuthoritiesConverter authorityConverter = new JwtGrantedAuthoritiesConverter();
        // 从Azure AD的"roles" Claim中提取角色,添加ROLE_前缀适配Spring Security权限规则
        authorityConverter.setAuthoritiesClaimName("roles");
        authorityConverter.setAuthorityPrefix("ROLE_");

        JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
        converter.setJwtGrantedAuthoritiesConverter(authorityConverter);
        // 设置Principal显示名称为JWT中的"name"字段(可选,默认是JWT对象本身)
        converter.setPrincipalClaimName("name");
        return converter;
    }
    */
}

4. 在业务代码中获取用户信息

配置完成后,可通过以下方式获取Principal和JWT中的用户数据:

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserInfoController {

    @GetMapping("/api/user/info")
    public String getUserDetails(@AuthenticationPrincipal Jwt jwt) {
        // 从JWT Claim中提取用户信息
        String userId = jwt.getClaim("sub");
        String userName = jwt.getClaim("name");
        String userEmail = jwt.getClaim("email");
        return String.format("用户ID:%s,用户名:%s,邮箱:%s", userId, userName, userEmail);
    }
}

关键细节说明

  • 为何permitAll仍返回401?:即使接口允许匿名访问,oauth2ResourceServer仍会对携带Token的请求进行签名和有效性验证,原有Keycloak配置的验证规则不兼容Azure AD的JWT,导致验证失败。
  • 为何移除oauth2ResourceServer后Principal为空?:此时Spring Security未执行认证流程,Authentication对象未被初始化,自然无法获取Principal。
  • 自定义转换器的作用:可以将Azure AD的roles/groups Claim映射为Spring Security的权限,或自定义Principal的显示内容,适配业务权限控制需求。

内容的提问来源于stack exchange,提问作者Armand Goupil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 05:03:29