【转】Microsoft Graph 桌面应用程序

桌面应用程序,在我这篇文章的语境中,我是特指在Windows桌面上面直接运行的.NET应用程序,包括Console Application,WPF Application,Windows Forms Application, UWP Application,并且限于篇幅,我只会以Console Application作为演示,因为无论表现形式如何不同,它们从本质上是类似的。

本文所附带示例代码可以通过https://github.com/chenxizhang/office365dev/tree/master/samples/graph-consoleapplicationsample 访问,这是由Visual Studio 2017编写,开发语言为C#,在Windows 10 Enterprise上面测试通过。请注意,作为演示目的,我尽可能在范例代码中仅包含最必要的代码。

注册Microsoft Graph应用程序

要进行具体的编程之前,你需要注册Microsfot Graph应用程序。本系列文章约定,针对国际版我将采用Azure AD 2.0这种方式进行注册,而针对中国版将采用Azure AD 1.0这种方式。这两种方式的详细操作步骤,以及我注册好的范例应用程序,请参考

注册Azure AD 2.0 应用程序

注册中国版Microsoft Graph应用程序

创建Console Application

不要问我怎么做这个事情,你应该知道的。 

考虑安全认证功能

关键是,接下来你该如何考虑呢?有的人会联想到OAuth,这是一个很好的想法。我在此前已经提到过如何分三个步骤实现Microsoft Graph应用开发,第一步是注册应用程序,第二步是实现身份认证,第三步就是该怎么调用你就怎么调用。

下图介绍了在Azure AD 2.0中支持的OAuth认证流程 

简单地说,OAuth认证一般会有三个步骤

  1. 客户端代表用户发起认证请求(通常是/authorize 这个地址),这个会跳转到Office 365的登录页面,让用户输入账号和密码
  2. 如果用户提供了正确的账号和密码,并确认授权,Azure AD会向我们在注册应用程序时提供的回调地址(redirectUrl)POST一个请求过来,附上一个code,然后我们的应用需要继续用这个code去发起一个请求,申请访问令牌(通常是/token这个地址)
  3. 客户端得到令牌(Access_Token),就可以代表用户访问Microsoft Graph的资源(通常是放在请求的头部里面)。这里需要注意的是,通常令牌都是会一定时间过期的,Micrsoft Graph的令牌默认为1小时有效。过期前可以通过一定的方式刷新令牌。

你当然可以在了解上述原理马上开始编写代码,但这里要请你了解,为了降低开发人员在这块的工作量,并且尽量进行标准化,Microsoft Graph针对不同的平台和语言都有对应的SDK。请参考 https://developer.microsoft.com/zh-cn/graph/docs/get-started/get-started

具体到我们本篇文章的目标,如果Office 365是国际版,你可以使用Microsoft Graph Client Library https://www.nuget.org/packages/Microsoft.Graph/  和 Microsoft Authentication Library https://www.nuget.org/packages/Microsoft.Identity.Client/1.0.304142221-alpha

目前这个 Microsoft Authentication Library 的状态是Preview,但是很值得期待,因为它还有针对.NET Core的版本

而如果是用中国版,你也可以使用 Active Directory Authentication Library .NET https://msdn.microsoft.com/library/en-us/Mt417579.aspx 

实现国际版Microsoft Graph调用

首先,运行下面的命令安装上面提到的两个Library,并且进行更新

Install-Package Microsoft.Graph
Install-Package Microsoft.Identity.Client -IncludePrereleaseUpdate-Package

接下来,我们需要编写一个方法,封装一下Graph Authentication这个步骤.

备注,我认为这里还有可以改进的空间,最好是连这一步都可以省略掉。产品组是还没有完全想好,日后应该会加上这块实现。

class GraphAuthenticator : IAuthenticationProvider
{static string token;static DateTimeOffset Expiration;public async Task AuthenticateRequestAsync(HttpRequestMessage request){string clientID = "45aa2ecc-5e57-4c91-86c1-b93064800c39";//这个ID是我创建的一个临时App的ID,请替换为自己的string[] scopes = { "user.read", "mail.read", "mail.send"};var app = new PublicClientApplication(clientID);AuthenticationResult result = null;try{result = await app.AcquireTokenSilentAsync(scopes);token = result.Token;}catch (Exception){if (string.IsNullOrEmpty(token) || Expiration <= DateTimeOffset.UtcNow.AddMinutes(5)){result = await app.AcquireTokenAsync(scopes);Expiration = result.ExpiresOn;token = result.Token;}}request.Headers.Add("Authorization", $"Bearer {token}");}
}

有了这个类,接下来我们要调用Microsoft Graph简直可以说是易如反掌,请参考下面的代码

var client = new GraphServiceClient(new GraphAuthenticator());//创建客户端代理
var user = client.Me.Request().GetAsync().Result;//获取当前用户信息
Console.WriteLine(user.DisplayName);var messages = client.Me.Messages.Request().GetAsync().Result;//获取用户的前十封邮件
foreach (var item in messages)
{Console.WriteLine(item.Subject);
}client.Me.SendMail(new Message() //发送邮件
{Subject = "调用Microsoft Graph发出的邮件",Body = new ItemBody(){ContentType = BodyType.Text,Content = "这是一封调用了Microsoft Graph服务发出的邮件,范例参考 https://github.com/chenxizhang/office365dev"},ToRecipients = new[]{new Recipient(){EmailAddress = new EmailAddress(){ Address ="ares@office365devlabs.onmicrosoft.com"}}}
}, true).Request().PostAsync();Console.Read();

完整代码,请参考 https://github.com/chenxizhang/office365dev/blob/master/samples/graph-consoleapplicationsample/graph-consoleapplicationsample/Program.cs

就是这么简单,就是这么任性,你可以马上运行这个应用程序看看效果了 

输入你的Office 365账号和密码(请注意,需要是国际版),然后点击“Sign In”,Microsoft Graph将引导你进行授权确认 

不出意外的话,你现在就可以在控制台窗口中看到当前登录的用户信息,十个邮件标题等信息了。

VB.NET 开发人员看过来

我不止一次听到开发人员反馈说,现在在网络上想一些VB或者VB.NET的代码范例比较难。这是一个事实,我自己对VB是有感情的,为了向这部分开发人员致意,我特别提供了一个VB.NET的版本。

我不能担保后续每一篇,每个范例都会提供VB.NET的版本,因为精力真的很有限。如果你有兴趣根据我的C#的范例转换为VB.NET代码,欢迎跟我联系。

Imports System.Net.Http
Imports Microsoft.Graph
Imports Microsoft.Identity.Client
''' <summary>
''' 这个是国际版Microsoft Graph的客户端应用程序范例
''' 作者:陈希章
''' 时间:2017年3月23日
''' </summary>
Module Module1Sub Main()Dim serviceClient = New GraphServiceClient(New GraphAuthenticator())Dim user = serviceClient.Me.Request.GetAsync().Result'获取用户基本信息Console.WriteLine(user.DisplayName)Console.WriteLine(user.Mail)'获取用户的邮件列表Dim messages = serviceClient.Me.MailFolders.Inbox.Messages.Request.GetAsync().ResultFor Each item In messagesConsole.WriteLine(item.Subject)Next'发送邮件serviceClient.Me.SendMail(New Message() With {.Subject = "调用Microsoft Graph发出的邮件(VB.NET)",.Body = New ItemBody() With {.Content = "这是一封调用了Microsoft Graph服务发出的邮件,范例参考 https://github.com/chenxizhang/office365dev",.ContentType = BodyType.Text},.ToRecipients = New List(Of Recipient) From {New Recipient() With {.EmailAddress = New EmailAddress() With {.Address = "ares@office365devlabs.onmicrosoft.com"}}}}, True).Request.PostAsync()Console.Read()End SubPublic Class GraphAuthenticatorImplements IAuthenticationProviderShared token As StringShared Expiration As DateTimeOffsetPublic Async Function AuthenticateRequestAsync(request As HttpRequestMessage) As Task Implements IAuthenticationProvider.AuthenticateRequestAsyncDim clientID As String = "45aa2ecc-5e57-4c91-86c1-b93064800c39" '这个ID是我创建的一个临时App的ID,请替换为自己的Dim scopes As String() = {"user.read", "mail.read", "mail.send"}Dim app As PublicClientApplication = New PublicClientApplication(clientID)Dim result As AuthenticationResultTryresult = Await app.AcquireTokenSilentAsync(scopes)token = result.TokenCatch ex As ExceptionIf (String.IsNullOrEmpty(token) OrElse Expiration <= DateTimeOffset.UtcNow.AddMinutes(5)) Thenresult = app.AcquireTokenAsync(scopes).ResultExpiration = result.ExpiresOntoken = result.TokenEnd IfEnd Tryrequest.Headers.Add("Authorization", $"Bearer {token}")End FunctionEnd ClassEnd Module

实现中国版Microsoft Graph调用

接下来我们该看看在中国版Microsoft Graph调用方面有什么不同。虽然因为没有封装好的Microsoft Graph Client,但是看起来基本代码也还算简单易懂,请参考。

安装下面这个Package

Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory
Update-Package

编写一个自定义方法获取用户的访问令牌

static async Task<string> GetAccessToken()
{var appId = "9c7dd51c-072c-4aea-aaee-fc57efacb150";var authorizationEndpoint = "https://login.chinacloudapi.cn/common/oauth2/authorize";//国际版是https://login.microsoftonline.com/common/oauth2/authorizevar resource = "https://microsoftgraph.chinacloudapi.cn"; //国际版是https://graph.microsoft.com var redirectUri = "http://nativeapplication";//其实这个应该去掉,目前必须要填,而且要跟注册时一样AuthenticationResult result = null;var context = new AuthenticationContext(authorizationEndpoint);result = await context.AcquireTokenAsync(resource, appId, new Uri(redirectUri), new PlatformParameters(PromptBehavior.Always));return result.AccessToken;
}

编写一个自定义方法发起Microsoft Graph请求


/// <summary>
/// 定义这个方法用来进行Rest调用
/// </summary>
/// <param name="url"></param>
/// <param name="token"></param>
/// <returns></returns>
static async Task<string> InvokeRestReqeust(string url, string token)
{var client = new System.Net.WebClient();client.Headers.Add("Authorization", $"Bearer {token}");var result = await client.DownloadStringTaskAsync(url);return result;//请注意,这里直接返回字符串型的结果,它是Json格式的,有兴趣的可以继续在这个基础上进行处理
}

万事俱备,下面就可以在主程序中组合使用这两个方法进行Microsoft Graph调用了

static void Main(string[] args)
{///获得用户的令牌var token = GetAccessToken().Result;//获得用户的基本信息var me = InvokeRestReqeust("https://microsoftgraph.chinacloudapi.cn/v1.0/me", token).Result;Console.WriteLine(me);//获得用户的邮件列表(前十封)var messages = InvokeRestReqeust("https://microsoftgraph.chinacloudapi.cn/v1.0/me/messages", token).Result;Console.WriteLine(messages);Console.Read();}

VB.NET用户看过来

我同样为这个范例准备了一个VB.NET的版本,请大家参考

Imports System.Net
Imports Microsoft.IdentityModel.Clients.ActiveDirectoryModule Module1Sub Main()'获得用户令牌Dim token = GetAccessToken().Result'获得当前用户基本信息Dim user = InvokeRestRequest("https://microsoftgraph.chinacloudapi.cn/v1.0/me", token).ResultConsole.WriteLine(user)'获得用户的邮件列表(前十封)Dim messages = InvokeRestRequest("https://microsoftgraph.chinacloudapi.cn/v1.0/me/messages", token).ResultConsole.WriteLine(messages)Console.Read()End SubAsync Function InvokeRestRequest(url As String, token As String) As Task(Of String)Dim client = New WebClient()client.Headers.Add("Authorization", $"Bearer {token}")Dim result = Await client.DownloadStringTaskAsync(url)Return result'请注意,这里直接返回字符串型的结果,它是Json格式的,有兴趣的可以继续在这个基础上进行处理End FunctionAsync Function GetAccessToken() As Task(Of String)Dim appId = "9c7dd51c-072c-4aea-aaee-fc57efacb150"Dim authorizationEndpoint = "https://login.chinacloudapi.cn/common/oauth2/authorize"'国际版是https://login.microsoftonline.com/common/oauth2/authorizeDim resource = "https://microsoftgraph.chinacloudapi.cn" '国际版是https://graph.microsoft.comDim redirectUri = "http://nativeapplication" '其实这个应该去掉,目前必须要填,而且要跟注册时一样Dim result As AuthenticationResultDim context = New AuthenticationContext(authorizationEndpoint)result = Await context.AcquireTokenAsync(resource, appId, New Uri(redirectUri), New PlatformParameters(PromptBehavior.Auto))Return result.AccessTokenEnd FunctionEnd Module

从上面的代码对照来看,Azure AD 1.0的方式,需要开发人员处理更多细节,例如身份验证,服务调用结果处理等等。如果有兴趣并且有能力的朋友,欢迎在这个基础上做一定的封装,简化开发。

本文所有代码范例,可以通过 https://github.com/chenxizhang/office365dev/tree/master/samples/graph-consoleapplicationsample 查看或者下载 

结语

本文完整地介绍了针对国际版和中国版Office 365,在桌面应用程序中如何实现Microsoft Graph的集成。针对国际版,我采用的是Azure AD 2.0的方式;针对中国版,我采用的是Azure AD 1.0的方式。同时,为了照顾到VB.NET的开发人员,本文所有范例都提供了VB.NET的版本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/437640.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】Microsoft Graph Web应用程序极致开发体验

前言 这篇文章最早写于2017年5月2日&#xff0c;当时的想法是从最简单的方式来写如何在一个ASP.NET MVC应用程序中集成Microsoft Graph&#xff0c;但实际上还真不是那么简单&#xff0c;至少我是不满意的&#xff0c;加上这一两周都比较忙&#xff0c;所以这一篇就一直搁置。…

Spark(idea)操作mysql进行查询和插入 (代码+理解)

首先在maven中加入配置 <!--mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.27</version></dependency>然后在idea配置数据库 1&#xff09; 查询 //1.查询数…

【转】在无人值守程序(服务)中调用Microsoft Graph

什么是无人值守程序&#xff08;服务&#xff09; 我在此前用了几篇文章分别介绍了在桌面应用程序&#xff08;控制台&#xff09;&#xff0c;Web应用程序&#xff08;ASP.NET MVC&#xff09;&#xff0c;以及PowerSehll脚本中如何访问Microsoft Graph&#xff0c;今天这一篇…

【转】使用PowerApps快速构建基于主题的轻业务应用 —— 入门篇

前言 在上一篇文章 基于Office 365的随需应变业务应用平台 中我提到&#xff0c;随着随需应变的业务需要&#xff0c;以及技术的发展&#xff0c;业务应用的开发的模式也有了深刻的变化。基于微软的平台&#xff0c;有服务于主干业务应用的Dynamic 365 业务应用平台&#xff0…

Spark内核源码学习(暂未学完)

1&#xff09; 回顾 1.1 Spark通用运行流程概述 在submit任务条件是需要指定executo个数&#xff0c;executor-CUP个数&#xff0c;可以提高并行度。 什么是并行&#xff0c;什么是并发&#xff1f; 并发&#xff1a;假如有多个任务task&#xff0c;并行是在一个cup中&#x…

【转】使用PowerApps快速构建基于主题的轻业务应用 —— 进阶篇

在上一篇 使用PowerApps快速构建基于主题的轻业务应用 —— 入门篇 中&#xff0c;我用了三个实际的例子演示了如何快速开始使用PowerApps构建轻业务应用&#xff0c;你可能已经发现&#xff0c;我都是使用默认生成的设置&#xff0c;没有做任何修改。当然&#xff0c;那样做出…

Spark一些组件的定义

Driver program: 运行应用程序的main函数并创建SparkContext的进程 除了RDD的最终执行所写的业务逻辑&#xff0c;剩下的都在Driver里生成&#xff0c;Driver端执行action算子才会到开始执行所创建的DAG-RDD图。 Cluster manager&#xff1a; 用于获取集群资源外部服务 Mas…

【转】D365 FO第三方集成(二)---访问认证(获取访问令牌)

D365 FO 在github上发布了第三方访问D365 FO的示例代码&#xff0c;里面包含了各种调用示例&#xff0c;代码很清晰。https://github.com/microsoft/Dynamics-AX-Integration 这篇blog简单分析一下代码中获取访问令牌的部分代码。 与获取访问令牌相关的代码有两个类ClientConfi…

【转】D365 FO第三方集成(三)---服务实现

D365 FO的Custom Service的实现比AX2012简单了很多。 AX2012服务方法要用属性SysEntryPointAttribute标记&#xff0c;添加到Services以后&#xff0c;还要发布服务并在系统管理入站端口添加操作&#xff0c;服务运行在CIL下&#xff0c;所以每次改动服务方法的代码都要增量生成…

PHP连接sql seaver数据库

我的PHP版本7.0 通过sqlsrv系列函数&#xff0c;需要下载安装Microsoft Drivers for PHP for SQL Server驱动&#xff1a; 地址&#xff1a;https://msdn.microsoft.com/library/dn865013.aspx。 根据自己需求下载安装&#xff0c;安装地址php下ext目录下&#xff0c;我的是4.0…

NoSql理解+传统关系型数据库ACID+Nosql的CAP+BASE的理解

1&#xff09;什么是Nosql NoSQL(NoSQL Not Only SQL )&#xff0c;意即“不仅仅是SQL”&#xff0c; 泛指非关系型的数据库。随着互联网web2.0网站的兴起&#xff0c;传统的关系数据库在应付web2.0网站&#xff0c;特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显…

ztree 点击重载 layui table

ztree 点击重载 layui table <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <HTML> <HEAD><TITLE> ztree_demo </TITLE><meta http…

数据结构与算法 - 稀疏数组(理解+代码实现案例)

举例 稀疏数组第一行是原数据几行几列和几个有效数据的个数 下面的行是各个有效数组的行列与具体值 稀疏数组实现 代码实现 package DataStructures.sparsearray;/*** 二维数组转稀疏数组 与 稀疏数组转成二维数组*/ public class SparseArray {public static void main(Stri…

数据结构 - 队列(非环形队列,以及优化成环形队列)

1&#xff09;队列的定义与实现形式-方式 2&#xff09;队列实现思路&#xff08;非环形&#xff0c;下面进行优化&#xff09; 3&#xff09;代码实现&#xff08;注意并不是环形&#xff09; package DataStructures.queue;import java.util.Scanner;/*** 使用数组模拟队列*…

爬取网易云音乐歌曲特色榜单信息

网易云音乐(iframe内的歌单) 刚开始学习做下记录 需要先下载好所需浏览器内核 我时谷歌&#xff0c;下载地址 http://chromedriver.storage.googleapis.com/index.html 然后没了&#xff0c;自己F12扒拉下就行了 运行&#xff1a; 左侧随便点击一个榜单后&#xff0c;复制ur…

数据结构 - 单链表(Linked List)实现在内存中实现数据以链表形式生成并根据序号排序

下面实现一个例子来进行学习 1&#xff09;介绍 单链表的逻辑结构 在内存中的实际结构 具体创建示意图&#xff1a; 2&#xff09;代码实现 例子 1。第一个程序在添加的时候并没有按照序号排序&#xff0c;如果在添加的时候把位置改变输出的时候序号会改变 package DataStr…

Mysql count() 语句

百万数据测试 select count(主键) from table 执行效率&#xff1a; select count(*) AS AGGREGATE from table 以上测试均再 navicat 工具进行 由于各种原因&#xff0c;sql执行时间可定存在一定误差&#xff0c;但最终结果不变。

phpStydy+wordpress 安装部署

1、先准备工具包 下载phpstudy&#xff0c;下载地址&#xff1a;https://www.xp.cn/ 下载wordpress &#xff0c;下载地址&#xff1a;https://cn.wordpress.org/download/ 2、安装phpStudy&#xff0c;下一步操作即可 3、安装完成后&#xff0c;检测环境配置&#xff0c;php、…

java数据结构 - 单链表(腾讯面试题实现单链表反转)

直接上实现代码 //单链表的反转public static void reverseList(HeroNode head){//如果当前链表为空&#xff0c;或只有一个节点&#xff0c;无需反转if (head.next null || head.next.next null){return ;}//定义一个辅助变量&#xff0c;帮助我们遍历HeroNode cur head.n…

数据结构 - 链表(双向链表学习)

程序里有几个注释的地方还是需要特别注意的&#xff0c;根据单链表自己的逻辑来写一遍双向链表&#xff0c;可能有几个细节处理的不到位。 package DataStructures.LinkedList;public class DoubleLinkedListDemo {public static void main(String []args){System.out.println…