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

从Azure AD获取已登录用户照片的C#示例代码请求

Azure AD旧版Graph获取用户照片的C#实现

前置要求

  • 你的Azure AD应用已配置User.Read或User.ReadBasic.All权限(委派权限用于用户登录场景,应用权限用于后台无用户交互场景),且已完成权限同意
  • 已获取登录用户的tenantId(可从Claims的http://schemas.microsoft.com/identity/claims/tenantid字段获取)和userId(http://schemas.microsoft.com/identity/claims/objectidentifier字段)

示例代码

首先安装ADAL NuGet包:

Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory

核心实现类

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Clients.ActiveDirectory;

public class AdGraphPhotoService
{
    // 从应用配置读取以下参数
    private readonly string _clientId = "你的应用Client ID";
    private readonly string _clientSecret = "你的应用Client Secret"; // 机密客户端时使用
    private readonly string _tenantId = "你的租户ID";
    private readonly string _graphApiVersion = "2013-11-08";
    private readonly string _graphBaseUrl = "https://graph.windows.net";

    /// <summary>
    /// 获取指定用户的照片字节数组
    /// </summary>
    /// <param name="userId">用户Object ID</param>
    /// <param name="useDelegatedToken">是否使用用户委派的访问令牌(用户已登录场景)</param>
    /// <param name="userAccessToken">用户登录后的访问令牌(useDelegatedToken为true时必填)</param>
    /// <returns>照片字节数组,无照片时抛出HttpRequestException</returns>
    public async Task<byte[]> GetUserPhotoAsync(string userId, bool useDelegatedToken = false, string userAccessToken = null)
    {
        AuthenticationResult authResult;
        var authContext = new AuthenticationContext($"{_graphBaseUrl}/{_tenantId}");

        if (useDelegatedToken)
        {
            // 委派权限场景:用当前用户的令牌获取Graph访问权限
            if (string.IsNullOrEmpty(userAccessToken))
                throw new ArgumentException("用户访问令牌不能为空", nameof(userAccessToken));
            
            var userAssertion = new UserAssertion(userAccessToken, "urn:ietf:params:oauth:grant-type:jwt-bearer");
            authResult = await authContext.AcquireTokenAsync(
                $"{_graphBaseUrl}/.default", 
                new ClientCredential(_clientId), 
                userAssertion);
        }
        else
        {
            // 应用权限场景:用客户端凭证获取Graph访问权限
            var clientCred = new ClientCredential(_clientId, _clientSecret);
            authResult = await authContext.AcquireTokenAsync(
                $"{_graphBaseUrl}/.default", 
                clientCred);
        }

        // 调用旧版Graph照片端点
        using (var httpClient = new HttpClient())
        {
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
            var photoEndpoint = $"{_graphBaseUrl}/{_tenantId}/users/{userId}/photo/$value?api-version={_graphApiVersion}";
            
            var response = await httpClient.GetAsync(photoEndpoint);
            if (response.IsSuccessStatusCode)
            {
                return await response.Content.ReadAsByteArrayAsync();
            }
            else
            {
                var errorContent = await response.Content.ReadAsStringAsync();
                throw new HttpRequestException($"获取照片失败:状态码 {response.StatusCode},详情:{errorContent}");
            }
        }
    }
}

使用示例(ASP.NET MVC场景)

public async Task<ActionResult> UserPhoto()
{
    // 从当前登录用户的Claims获取租户ID和用户ID
    var tenantId = User.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid")?.Value;
    var userId = User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value;
    
    // 获取用户的访问令牌
    var userAccessToken = Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
    
    var photoService = new AdGraphPhotoService();
    try
    {
        var photoBytes = await photoService.GetUserPhotoAsync(userId, true, userAccessToken);
        return File(photoBytes, "image/jpeg");
    }
    catch (HttpRequestException ex)
    {
        // 处理无照片或权限错误
        return Content("无法获取用户照片:" + ex.Message);
    }
}

关键注意点

  • 若返回404状态码,说明该用户未在Azure AD中上传照片
  • 应用权限需要管理员在Azure AD门户中完成权限同意
  • 委派权限场景下,确保用户登录时的scope包含User.Read或等效权限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:40:35