我正尝试使用Microsoft Graph承载令牌从Sharepoint下载文件。我继续收到401未授权响应。该应用程序将从Azure内运行,但在我确定该应用程序时,该应用程序当前在本地运行。代码如下所示,注解代替了可能的敏感信息:
using System.Net.Http.Headers;
using System.Text;
namespace SharePointFileDownload
{
class Program
{
static async Task Main(string[] args)
{
try
{
string tenantId = /*My company's tenantId, from Azure*/;
string accessToken = await GetGraphBearerToken();
string tenant = /*the name of the tenant on sharepoint*/;
string siteName = /*sharepoint site name*/;
string library = /*sharepoint library name*/;
string fileName = /*filename of the test document*/;
string fileUrl = $"https://{tenant}.sharepoint.com/sites/{siteName}/{library}/{fileName}";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
string graphRequestUrl = $"https://graph.microsoft.com/v1.0/tenants/{tenantId}/drives/root:{fileUrl.Substring(fileUrl.IndexOf("/sites"))}:/content";
HttpResponseMessage response = await client.GetAsync(graphRequestUrl);
if (response.IsSuccessStatusCode)
{
byte[] fileContent = await response.Content.ReadAsByteArrayAsync();
File.WriteAllBytes("file.docx", fileContent);
Console.WriteLine("File downloaded successfully.");
}
else
{
Console.WriteLine("Failed to download file. Error: " + response.ReasonPhrase);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
public static async Task<string> GetGraphBearerToken()
{
try
{
string clientId = /*Azure ClientId for the registered application*/;
string clientSecret = /*Azure ClientSecret for the registered application*/;
string tenantId = /*My company's tenantId, same as in the main method*/;
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
var requestBody = new StringContent($"grant_type=client_credentials&client_id={clientId}&client_secret={clientSecret}&scope=https://graph.microsoft.com/.default", Encoding.UTF8, "application/x-www-form-urlencoded");
var response = await client.PostAsync($"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token", requestBody);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
// parse the responseContent to get the bearer token
Console.WriteLine("Bearer token: " + responseContent);
return responseContent;
}
else
{
Console.WriteLine("Error fetching bearer token: " + response.StatusCode);
return String.Empty;
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
return String.Empty;
}
}
}
}
上面的代码是从各种教程中汇编出来的。它成功地获取了一个令牌并将其返回给main方法,但随后我得到了一个401未经授权的响应。
我向ClientId和ClientSecret所针对的Azure应用程序添加了许多权限,包括Microsoft_Graph/Files.ReadWrite.All和Microsoft_Graph/Sites. ReadWrite. All。
任何有Sharepoint和Graph经验的人告诉我哪里出了问题?或者代码是否可以以任何方式优化?非常感谢。
附言:下面是我得到的完整回复的一个例子,如果有帮助的话:
StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers:
{
Transfer-Encoding: chunked
Strict-Transport-Security: max-age=31536000
request-id: /*An ID, the same as client-request-id*/
client-request-id: /*An ID, the same as request-id*/
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"South Central US","Slice":"E","Ring":"5","ScaleUnit":"004","RoleInstance":/*Not sure if this is private, but here is a comment anyway*/}}
WWW-Authenticate: Bearer realm="", authorization_uri="https://login.microsoftonline.com/common/oauth2/authorize", client_id=/*A ClientId that does not match the clientId variable I passed*/
Date: Tue, 21 Feb 2023 16:55:47 GMT
Content-Type: application/json
}
1条答案
按热度按时间bfnvny8b1#
我同意*@TinyWang * 和*@user2250152 ,您需要在使用客户端凭据流程时添加*
Application
类型的API权限。但是,当我添加
Application
权限后运行您的代码时,仍然出现未经授权**错误。我尝试在我的环境中重现相同的结果,结果如下:
我有一个名为**
TestDocLib
的SharePoint文档库**,其文件如下:我注册了一个Azure AD应用程序,并添加了**
Application
类型的相同API权限**,如下所示:当我运行与您相同的**c#代码时,我也获得了访问令牌,并出现如下
Unauthorized
**错误:当我解码上述访问令牌时,它具有两个权限的**
roles
声明,确认令牌是valid**,如下所示:要知道问题的确切位置,请尝试在Postman中运行相同的查询,并检查是否得到相同的结果。
在我的例子中,我通过包含上述访问令牌在Postman中运行了不同的图形查询,并在响应中获得了文件下载链接,如下所示:
当我复制上述下载链接并在浏览器中运行时,文件成功下载,如下所示:
为了确认这一点,我检查了相同的文件资源管理器,并发现**
sri12.docx
**文件在下载文件夹中,如下所示:要在C#中运行相同的查询,您可以使用以下代码: