到了春暖花开的四月了,又要开始努力成长了。虽然口罩还没摘下,我们坚信疫情会过去,一切都会好起来的。
许久不写,介绍一篇“磨刀”文。
本篇讲述如何使用Visual Studio在桌面程序中调用Microsoft Graph,调用方式为简单易学的SDK方式,以C#为例。
首先你需要在Microsoft Identity平台注册一个应用程序,这个之前说过几遍就不再赘述了,忘了的点这里。
在Visual Studio中新建一个控制台应用,然后执行如下命令安装所需的NuGet包。控制台程序可以用来写一些定期跑的任务或者是无人值守进程这种东西。
Install-Package Microsoft.Graph
Install-Package Microsoft.Graph.Auth -IncludePrerelease
Install-Package Microsoft.Extensions.Configuration.Json
前两个是调用Graph所需的东西,后面的一个是解析Json用的。
以SDK方式调用Graph的概要流程为通过我们注册的应用程序的信息去构建GraphServiceClient对象,然后通过这个client去请求我们要获取的信息。
首先创建一个Json文件用来存储应用程序信息,例如appsettings.json,示例内容如下:
{
"tenantId": "<your tenent id>",
"applicationId": "<your client id>"
}
本示例需用户手动输入凭据信息,所以只需要tenant id和client id就可以了。
创建一个认证提供程序类MsalAuthenticationProvider,用于处理用户凭据认证等相关工作。
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security;
using System.Threading.Tasks;
using Microsoft.Identity.Client;
using Microsoft.Graph;
namespace MSGraphPractice
{
public class MsalAuthenticationProvider : IAuthenticationProvider
{
private static MsalAuthenticationProvider _singleton;
private IPublicClientApplication _clientApplication;
private string[] _scopes;
private string _username;
private SecureString _password;
private string _userId;
private MsalAuthenticationProvider(IPublicClientApplication clientApplication, string[] scopes, string username, SecureString password)
{
_clientApplication = clientApplication;
_scopes = scopes;
_username = username;
_password = password;
_userId = null;
}
public static MsalAuthenticationProvider GetInstance(IPublicClientApplication clientApplication, string[] scopes, string username, SecureString password)
{
if (_singleton == null)
{
_singleton = new MsalAuthenticationProvider(clientApplication, scopes, username, password);
}
return _singleton;
}
public async Task AuthenticateRequestAsync(HttpRequestMessage request)
{
var accessToken = await GetTokenAsync();
request.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
}
public async Task<string> GetTokenAsync()
{
if (!string.IsNullOrEmpty(_userId))
{
try
{
var account = await _clientApplication.GetAccountAsync(_userId);
if (account != null)
{
var silentResult = await _clientApplication.AcquireTokenSilent(_scopes, account).ExecuteAsync();
return silentResult.AccessToken;
}
}
catch (MsalUiRequiredException) { }
}
var result = await _clientApplication.AcquireTokenByUsernamePassword(_scopes, _username, _password).ExecuteAsync();
_userId = result.Account.HomeAccountId.Identifier;
return result.AccessToken;
}
}
}
在Program.cs文件中,加入以下方法。
private static IConfigurationRoot LoadAppSettings()
{
try
{
var config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false, true)
.Build();
if (string.IsNullOrEmpty(config["applicationId"]) ||
string.IsNullOrEmpty(config["tenantId"]))
{
return null;
}
return config;
}
catch (System.IO.FileNotFoundException)
{
return null;
}
}
private static IAuthenticationProvider CreateAuthorizationProvider(IConfigurationRoot config, string userName, SecureString userPassword)
{
var clientId = config["applicationId"];
var authority = $"https://login.microsoftonline.com/{config["tenantId"]}/v2.0";
List<string> scopes = new List<string>();
scopes.Add("User.Read");
scopes.Add("Files.Read");
var cca = PublicClientApplicationBuilder.Create(clientId)
.WithAuthority(authority)
.Build();
return MsalAuthenticationProvider.GetInstance(cca, scopes.ToArray(), userName, userPassword);
}
private static GraphServiceClient GetAuthenticatedGraphClient(IConfigurationRoot config, string userName, SecureString userPassword)
{
var authenticationProvider = CreateAuthorizationProvider(config, userName, userPassword);
var graphClient = new GraphServiceClient(authenticationProvider);
return graphClient;
}
private static SecureString ReadPassword()
{
Console.WriteLine("Enter your password");
SecureString password = new SecureString();
while (true)
{
ConsoleKeyInfo c = Console.ReadKey(true);
if (c.Key == ConsoleKey.Enter)
{
break;
}
password.AppendChar(c.KeyChar);
Console.Write("*");
}
Console.WriteLine();
return password;
}
private static string ReadUsername()
{
string username;
Console.WriteLine("Enter your username");
username = Console.ReadLine();
return username;
}
并在Main方法中使用以下代码进行调用。
var config = LoadAppSettings();
if (config == null)
{
Console.WriteLine("Invalid appsettings.json file.");
return;
}
var userName = ReadUsername();
var userPassword = ReadPassword();
var client = GetAuthenticatedGraphClient(config, userName, userPassword);
//your request code
var request = client.Me.Request();
var result = request.GetAsync().Result;
Console.WriteLine(result.DisplayName);
Console.ReadKey();
具体要执行什么就要视具体的需要而定了,但基本方式都是类似这样的。
上面涵盖了全部的代码,照着操作就能用,本来想传到git上但是一直报错弄不上去,算了。