Невозможно получить ProjectContext для Project Online из SharePoint Office 365 и получить ошибку 403 в .NET 8

У меня есть опыт работы с .NET, но я довольно новичок в Sharepoint и Project Online. Мне любопытно, МИД это или что происходит, но я всегда получаю

The remote server returned an error: (403) FORBIDDEN

Для кода

public async Task<ProjectContext?> GetContextWithCredentialsAsync(string url, string username, string password)
{
    try
    {
        if (url.ToUpper().StartsWith("HTTP://") || url.ToUpper().StartsWith("HTTPS://"))
        {
            var securePassword = new SecureString();
            password.ToCharArray().ToList().ForEach(s => securePassword.AppendChar(s));

            var clientContext = new ProjectContext(url)
            {
                
                Credentials = new NetworkCredential(username, securePassword)
        };
            clientContext.Load(clientContext.Projects);
            clientContext.ExecuteQuery();

            return await System.Threading.Tasks.Task.Factory.StartNew(() => { return clientContext; });
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }

    return null;
}

Я видел в Интернете другой подобный код, делающий это, и думаю, возможно, это MFA, и мне нужно получить аутентификацию, но другие ссылки, которые я видел, были старше .NET. Я использую библиотеку: «Microsoft.SharePointOnline.CSOM» версии 16.1.24810.12000 в веб-API .NET 8, вызывая приведенный выше код.

Редактировать: Кажется, вам нужно использовать Энтру и что-то еще, но мне нужен лучший ответ, которым смогут воспользоваться все. Очень грустно, когда документы MS ошибаются. Кто-то должен знать ответ, который мы можем написать для .NET 8, а НЕ для полной платформы.

Самый близкий вариант, который у меня есть, требует clientId и tenantId, но это было сделано через Azure. Можете ли вы сделать это для виртуальной машины напрямую, без приложения Azure?

public async System.Threading.Tasks.Task 
CreateConnectionProjectContext(string baseUrl, string url, string username, string password, string clientId, string tenantId)
{
        var pcaConfig = PublicClientApplicationBuilder.Create(clientId).WithTenantId(tenantId);

        var TokenResult = await pcaConfig.Build().AcquireTokenByUsernamePassword(new[] { baseUrl }, username, password).ExecuteAsync();

        // Load ps context
        var projectContext = new ProjectContext(url);
        projectContext.ExecutingWebRequest += (s, e) =>
        {
            e.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + TokenResult.AccessToken;
        };

        projectContext.Load(projectContext.Projects);
        projectContext.ExecuteQuery();

        _context = projectContext;
}

}

Проблема в строке «var pcaConfig». Можете ли вы сделать это непосредственно в Entra без приложения Azure?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
323
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

.NET Framework

Вам необходимо использовать поддержку SharePointOnlineCredentials для учетных данных. Также будьте осторожны и используйте правильный URL-адрес pwa (из документации):

В этом примере URL-адрес должен быть равен: «https://Contoso.sharepoint.com/sites/pwa».

//URL should contain the pwa url ex: https://Contoso.sharepoint.com/sites/pwa
 var clientContext = new ProjectContext(url);

 var netcred = new NetworkCredential(username, password);
 var orgIDCredential = new SharePointOnlineCredentials(netcred.UserName, netcred.SecurePassword);
 clientContext.Credentials = orgIDCredential;

 var projects = clientContext.Load(clientContext.Projects);
 clientContext.ExecuteQuery();

 if (projects.Any())
   // use projects

Полный пример создания полей проекта и обновления: https://github.com/OfficeDev/Project-Samples/tree/main/Create-Update-Project-Samples/Create-Update-Project-Samples

[EDIT]: Отличие .Net Core/Framework

.NET Core/.NET 8

Как вы упомянули в комментарии, SharePointOnlineCredentials не существует. Вам нужно будет получить токен доступа OAuth, создав регистрацию приложения и предоставив ему разрешение Sharepoint:

  1. В Microsoft Entra ID (Azure AD) создайте новую регистрацию приложения.
  2. В разрешении API добавьте разрешение и выберите Sharepoint.
  3. Затем настройте делегированные разрешения для Project (если вам нужно только чтение, или только запись, или и то, и другое). Вы также можете запросить AllSites.Manage, но для этого потребуется согласие администратора.
  4. В разделе «Аутентификация» измените «Разрешить потоки общедоступных клиентов» на «Да».
  5. Из обзора скопируйте идентификатор приложения, который вы будете использовать в своем коде.

Теперь, когда у вас есть клиент, настроенный для получения токенов OAuth, вы можете получить токен, используя поток passwork из конечной точки токена Microsoft Entra ID https://login.microsoftonline.com/common/oauth2/token.

ПОСТ https://login.microsoftonline.com/common/oauth2/token Тело: ресурс=https://...sites//pwa&client_id = {appId}&grant_type=password&username = {username}&password = {userPass}.

Вы можете использовать HttpClient для публикации или использовать любую библиотеку OAuth для получения токена.

Если у вас есть токен, вы можете использовать ProjectContext для запроса Project:

var context = new ProjectContext(web);

context.ExecutingWebRequest += (sender, e) =>
{
    var accessToken = // Get AccessToken
    e.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + accessToken;
};

projectContext.Load(projectContext.Projects);
projectContext.ExecuteQuery();

Полный пример кода здесь (он использует ClientContext, но он похож): https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/using-csom-for-dotnet-standard

Нет, это стало толстым. Если вы откроете тикет с помощью Stack Overflow, я надеюсь, мы сможем его изменить. Я хотел «отдать» это вам, но страница перевернулась, и она перешла не на ту. И, конечно, вы не можете отменить это.

djangojazz 12.07.2024 19:55

@djangojazz, как только награда будет присуждена, ее нельзя будет переместить на другой ответ. Смотрите: Дали награду за неправильный ответ, что мне делать? и Должны ли мы позволить отменить ошибочное вознаграждение?

Dalija Prasnikar 13.07.2024 13:26

Другие вопросы по теме

Похожие вопросы

Как исправить значения положения мыши, чтобы они были большими в единице
WinUI 3 Как создать библиотеку пользовательских элементов управления
Несколько экземпляров объекта, предоставляемого посредством внедрения зависимостей
Могу ли я настроить автоматическое выполнение асинхронной операции после завершения другой асинхронной операции?
Как выбрать строку сетки данных, щелкнув за пределами содержимого
Как решить исключение «Неожиданный источник запроса: присоединиться к ICacheEntry в CacheQueryable» при выполнении левого соединения с использованием linq в Apache Ignite?
Вызов универсального метода расширения с типом, известным во время выполнения, в качестве аргумента
Получение ошибки «Данные имеют значение Null» при доступе к полям базы данных на C#. Почему «?» работает, а если оператор нет
Каков синтаксис XAML для передачи нескольких значений перечисления в параметр преобразователя в MAUI?
Используйте Task.WhenAll в уже работающем методе