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

ASP.NET MVC实现Office 365账号验证及用户信息获取方案咨询

在ASP.NET MVC中实现无跳转验证Office 365账号并获取用户信息

核心思路

要实现本地页面输入Office 365账号密码、不跳转至O365页面的验证逻辑,需采用Azure AD资源所有者密码凭证流(ROPC流)——直接通过用户名密码向Azure AD请求访问令牌,再用令牌调用Microsoft Graph API获取用户姓名、手机号等信息。注意:该流不支持开启多因素认证(MFA)的用户,需提前确认业务场景是否适用。

步骤1:Azure AD后台配置

  • 登录Azure门户,进入你的AD租户,注册一个Web类型的应用
  • 在应用的「认证」页面,开启「允许公共客户端流」(ROPC流依赖该配置)
  • 在「API权限」页面,添加Microsoft Graph的委派权限:User.Read(获取基础用户信息)、User.ReadBasic.All(如需扩展信息),点击「授予管理员同意」(否则普通用户无法使用该权限)
  • 记录应用的客户端ID和租户ID,后续代码会用到

步骤2:实现登录验证逻辑

在MVC的AccountController中编写登录处理Action,调用Azure AD令牌端点完成账号验证:

using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Newtonsoft.Json;

public class AccountController : Controller
{
    public ActionResult Login()
    {
        return View();
    }

    [HttpPost]
    public async Task<ActionResult> Login(string email, string password)
    {
        var clientId = "你的Azure应用客户端ID";
        var tenantId = "你的租户ID";
        var tokenEndpoint = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";

        using (var client = new HttpClient())
        {
            var requestContent = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("grant_type", "password"),
                new KeyValuePair<string, string>("client_id", clientId),
                new KeyValuePair<string, string>("username", email),
                new KeyValuePair<string, string>("password", password),
                new KeyValuePair<string, string>("scope", "https://graph.microsoft.com/User.Read")
            });

            var response = await client.PostAsync(tokenEndpoint, requestContent);
            if (!response.IsSuccessStatusCode)
            {
                ModelState.AddModelError("", "邮箱/密码错误,或账号开启了MFA无法使用该登录方式");
                return View();
            }

            var tokenJson = await response.Content.ReadAsStringAsync();
            var tokenResult = JsonConvert.DeserializeObject<TokenResponse>(tokenJson);

            // 将令牌和用户邮箱存入Session,供后续页面使用
            Session["O365AccessToken"] = tokenResult.AccessToken;
            Session["UserEmail"] = email;

            return RedirectToAction("Index", "Home");
        }
    }

    // 反序列化令牌响应的模型类
    private class TokenResponse
    {
        [JsonProperty("access_token")]
        public string AccessToken { get; set; }
        [JsonProperty("expires_in")]
        public int ExpiresIn { get; set; }
        [JsonProperty("token_type")]
        public string TokenType { get; set; }
    }
}

步骤3:首页获取用户信息

在HomeController的Index Action中,用已获取的令牌调用Graph API拉取用户信息:

using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Newtonsoft.Json;

public class HomeController : Controller
{
    public async Task<ActionResult> Index()
    {
        var accessToken = Session["O365AccessToken"] as string;
        if (string.IsNullOrEmpty(accessToken))
        {
            return RedirectToAction("Login", "Account");
        }

        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            // 按需指定要获取的字段,减少请求数据量
            var response = await client.GetAsync("https://graph.microsoft.com/v1.0/me?$select=displayName,mail,mobilePhone,givenName,surname");

            if (!response.IsSuccessStatusCode)
            {
                // 令牌过期或权限失效,跳转回登录页
                return RedirectToAction("Login", "Account");
            }

            var userJson = await response.Content.ReadAsStringAsync();
            var userInfo = JsonConvert.DeserializeObject<UserInfo>(userJson);

            ViewBag.UserInfo = userInfo;
            return View();
        }
    }

    // 用户信息模型类
    private class UserInfo
    {
        [JsonProperty("displayName")]
        public string DisplayName { get; set; }
        [JsonProperty("mail")]
        public string Email { get; set; }
        [JsonProperty("mobilePhone")]
        public string MobilePhone { get; set; }
        [JsonProperty("givenName")]
        public string FirstName { get; set; }
        [JsonProperty("surname")]
        public string LastName { get; set; }
    }
}

关键注意事项

  • 生产环境中,不要硬编码客户端ID、租户ID,建议存入web.config配置文件,通过ConfigurationManager.AppSettings读取
  • 必须使用HTTPS传输密码,避免明文泄露
  • 注意令牌过期时间,可通过返回的refresh_token实现令牌刷新,无需用户重复登录
  • 若业务涉及开启MFA的用户,该方案不适用,需切换为常规OAuth2授权码流程(但会跳转O365页面)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:20:19