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

Spring Boot后端无需用户认证查询Azure AD用户启用状态

解决方案

1. 配置Azure AD应用权限

在Azure门户的应用注册中,为你的Spring Boot应用添加应用权限:

  • 权限类型:应用权限
  • 选择Microsoft Graph → User.Read.All
  • 点击"授予管理员同意"(必须完成此步骤,否则应用无法查询用户状态)

2. 配置Spring Boot的OAuth2客户端凭证流

在application.properties中补充客户端凭证相关配置:

# 客户端凭证流配置
spring.security.oauth2.client.registration.azure-client.client-id=${azure.client-id}
spring.security.oauth2.client.registration.azure-client.client-secret=${azure.client-secret}
spring.security.oauth2.client.registration.azure-client.authorization-grant-type=client_credentials
spring.security.oauth2.client.provider.azure-client.token-uri=https://login.microsoftonline.com/${azure.tenant-id}/oauth2/v2.0/token
spring.security.oauth2.client.provider.azure-client.jwk-set-uri=https://login.microsoftonline.com/${azure.tenant-id}/discovery/v2.0/keys

3. 实现Azure AD用户状态查询服务

创建服务类,用于获取客户端凭证令牌并调用Microsoft Graph API查询用户启用状态:

import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Map;

@Service
public class AzureADUserStatusService {

    private final OAuth2AuthorizedClientService authorizedClientService;
    private final ClientRegistration clientRegistration;
    private final RestTemplate restTemplate;

    public AzureADUserStatusService(OAuth2AuthorizedClientService authorizedClientService,
                                    ClientRegistrationRepository clientRegistrationRepository) {
        this.authorizedClientService = authorizedClientService;
        this.clientRegistration = clientRegistrationRepository.findByRegistrationId("azure-client");
        this.restTemplate = new RestTemplate();
    }

    // 获取客户端凭证模式的访问令牌
    private String getClientCredentialsToken() {
        OAuth2AuthorizedClient authorizedClient = authorizedClientService.loadAuthorizedClient(
                clientRegistration.getRegistrationId(),
                "client-credentials"
        );
        if (authorizedClient == null || authorizedClient.getAccessToken().isExpired()) {
            authorizedClient = authorizedClientService.authorizeClient(clientRegistration, null);
        }
        return authorizedClient.getAccessToken().getTokenValue();
    }

    // 通过邮箱查询用户是否启用
    public boolean isUserEnabled(String userEmail) {
        String token = getClientCredentialsToken();
        String graphApiUrl = String.format(
                "https://graph.microsoft.com/v1.0/users?$filter=mail eq '%s'&$select=accountEnabled",
                userEmail
        );

        org.springframework.http.HttpHeaders headers = new org.springframework.http.HttpHeaders();
        headers.setBearerAuth(token);
        org.springframework.http.HttpEntity<String> entity = new org.springframework.http.HttpEntity<>(headers);

        Map<String, Object> response = restTemplate.exchange(
                graphApiUrl,
                org.springframework.http.HttpMethod.GET,
                entity,
                Map.class
        ).getBody();

        if (response != null && response.containsKey("value")) {
            List<Map<String, Object>> users = (List<Map<String, Object>>) response.get("value");
            if (!users.isEmpty()) {
                return (boolean) users.get(0).get("accountEnabled");
            }
        }
        return false;
    }
}

4. 实现定时检查清理任务

创建定时任务类,每24小时执行一次用户状态检查,删除禁用用户的凭证:

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class UserCredentialCleanupTask {

    private final AzureADUserStatusService azureADUserStatusService;
    private final UserCredentialRepository userCredentialRepository; // 替换为你的凭证仓储类

    public UserCredentialCleanupTask(AzureADUserStatusService azureADUserStatusService,
                                     UserCredentialRepository userCredentialRepository) {
        this.azureADUserStatusService = azureADUserStatusService;
        this.userCredentialRepository = userCredentialRepository;
    }

    // 每24小时执行一次(cron表达式:0 0 0 * * ?)
    @Scheduled(cron = "0 0 0 * * ?")
    public void cleanupDisabledUserCredentials() {
        userCredentialRepository.findAll().forEach(credential -> {
            boolean isEnabled = azureADUserStatusService.isUserEnabled(credential.getUserEmail());
            if (!isEnabled) {
                userCredentialRepository.delete(credential);
            }
        });
    }
}

5. 启用Spring定时任务

在Spring Boot启动类上添加@EnableScheduling注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

关键说明

  • 客户端凭证流:让应用以自身身份向Azure AD请求令牌,无需用户参与认证,适合后台定时任务场景。
  • 权限说明:User.Read.All应用权限是查询所有用户状态的必要条件,必须完成管理员授权。
  • API优化:通过$filter和$select参数精准过滤数据,减少不必要的网络传输。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 08:06:24