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
相关产品推荐
相关产品推荐

