Получить учетные данные Nuget, хранящиеся где-то в Visual Studio в проекте VSIX - PullRequest
0 голосов
/ 08 ноября 2018

Я разрабатываю расширение Visual Studio (проект VSIX), которому необходимо управлять пакетами Nuget для данного проекта.

Я уже использую сервис IVsPackageInstaller, так как задокументировано здесь но это ограничено, и мне нужно больше функций (например, получить номер последней версии данного пакета).

Я искал, но не нашел ничего о том, как программно взаимодействовать с диспетчером пакетов Visual Studio, поэтомуЯ решил использовать API Nuget напрямую.

Я отправляю HTTP-запросы к API Nuget, используя класс WebRequest (потому что мы не можем использовать HttpClient в проекте VSIX), но я нажимаюпроблема: запросы отправляются на частный канал Nuget, который требует аутентификации!(размещено в Azure DevOps)

Я использовал Fiddler для проверки HTTP-запросов, отправленных на наш сервер Azure DevOps.Я вижу POST-запрос, идущий на https://app.vssps.visualstudio.com/_apis/Token/SessionTokens с токеном в ответе, но это не токен, который я ищу.

Токен, переданный в API Nuget, - это токен Basic, полученный от Я не знаю, где.Я не смог найти этот токен в HTTP-ответах, которые я перехватил.

Я также вижу, что некоторые ответы на наш сервер DevOps Azure содержат такие заголовки (я изменил GUID)

WWW-Authenticate: Bearer authorization_uri=https://login.windows.net/ce372fcc-5e17-490b-ad99-47565dac8a84

Я могу найти этот GUID обратно в файле %userprofile%\AppData\Local\.IdentityService\AccountStore.json, здесь определенно что-то происходит.И файл SessionTokens.json в той же папке тоже выглядит интересно, но он зашифрован ...

Я также попытался покопаться в реестре, чтобы посмотреть, могу ли я найти интересную информацию, например, по пути, указанному в Комментарий Саймона , но, похоже, VS2017 больше не хранит токен там.

Я также загрузил файл privateregistry.bin (он же Visual Studio Settings Store) и искал везде, но ничего не смог найти.

Таким образом, вместо попытки перепроектировать Visual Studio, я хотел получить прямой доступ к провайдеру учетных данных.Я попытался получить доступ к нескольким службам и классам

var componentModel = await ServiceProvider.GetGlobalServiceAsync(typeof(SComponentModel)) as IComponentModel;
var credentialProvider = componentModel.GetService<IVsCredentialProvider>();
var credentialServiceProvider = componentModel.GetService<ICredentialServiceProvider>();
var defaultCredentialServiceProvider = new DefaultVSCredentialServiceProvider();

, но ни один из них не работает (возвращает ноль или исключение).

Я забрел в NuGet.PackageManagement.VisualStudio *Проект 1043 * на Github, но не смог найти мой ответ.

Существует также множество пакетов Nuget, таких как NuGet.PackageManagement.VisualStudio, Microsoft.VisualStudio.Services.Release.Client, Microsoft.VisualStudio.Services.ExtensionManagement.WebApi, Microsoft.VisualStudio.Services.InteractiveClient, и это лишь некоторые из них, но, честно говоря, я не знаю, есть ли то, что я ищу...

Так как получить доступ к учетным данным Nuget, используемым в Visual Studio?

Я использую любое решение, которое дает мне доступ ко всем функциям чтения Nuget, например, программно использует управление пакетами Visual Studio, или расшифровывает этот SessionTokens.json файл, или обращается к поставщику учетных данных Visual Studio.

Чем меньше хаки является ответом, тем лучше.

На данный момент вы, наверное, уже догадались, я не хочу хранить username и password где-то сам.Мне нужно создать удобное расширение VS, поэтому я хочу получить и использовать учетные данные, уже сохраненные в Visual Studio пользователями.

Большое спасибо за решение этой проблемы.

1 Ответ

0 голосов
/ 09 ноября 2018

NuGet Client SDK

Большое спасибо Саймону, который указал мне в направлении NuGet.Client .

Документация только от Microsoft содержит ссылку на блог 2016 от Дэйва Глика , но также содержит приятное замечание:

Эти сообщения в блоге были написаны вскоре после того, как была выпущена версия пакета SDK клиента NuGet 3.4.3. Более новые версии пакетов могут быть несовместимы с информацией в сообщениях в блоге.

Хорошо, тогда я думаю, что мы будем делать с блогом Дейва ...

Вам следует установить два пакета: NuGet.Client и Nuget.Protocol

Тогда вот код, например, чтобы получить последнюю версию пакета:

using NuGet.Configuration;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace MyProject
{
    public class NugetHelper
    {
        public async Task<string> GetLatestVersionNumberFromNugetFeedAsync(NugetPackage package)
        {
            try
            {
                Logger logger = new Logger(); //Just a class implementing the Nuget.Common.ILogger interface
                List<Lazy<INuGetResourceProvider>> providers = new List<Lazy<INuGetResourceProvider>>();
                providers.AddRange(Repository.Provider.GetCoreV3());  // Add v3 API support
                PackageSource packageSource = new PackageSource(package.Source.ToString());
                SourceRepository sourceRepository = new SourceRepository(packageSource, providers);
                PackageMetadataResource packageMetadataResource = await sourceRepository.GetResourceAsync<PackageMetadataResource>();
                var searchMetadata = await packageMetadataResource.GetMetadataAsync(package.Name, false, false, new SourceCacheContext(), logger, new CancellationToken());
                var versionNumber = searchMetadata.FirstOrDefault().Identity.Version.OriginalVersion;
                return versionNumber;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
    }

    public class NugetPackage
    {
        public string Name { get; set; }
        public string Version { get; set; }
        public string MinimumVersion { get; set; }
        public Uri Source { get; set; }
    }
}

Место хранения физических токенов

Я пытался выполнить обратный инжиниринг, где Visual Studio хранил токен, используемый в HTTP-запросах, к API Nuget.

Я экспортировал в текстовые файлы все кусты реестра, включая хранилище настроек Visual Studio (privateregistry.bin). Затем в Visual Studio добавлен новый канал Nuget, как и ожидалось, появилось всплывающее окно с входом, и я вошел в систему. Наконец я снова экспортировал все ульи в текстовые файлы и сравнил их все с файлами перед аутентификацией.

Я не нашел ничего интересного в VS Settings Store.

Единственные интересные изменения были

[HKEY_CURRENT_USER \ Software \ Microsoft \ VSCommon \ ConnectedUser \ IdeUserV2] @ = "0746fb8e-4bc2-4ee5-b804-0084af725deb" "AccountsRoaming_LastAccountsSettingVersion" = DWORD: 0000025b

[HKEY_CURRENT_USER \ Software \ Microsoft \ VsHub \ ServiceModules \ Settings \ PerHubName \ vshub \ ConnectedUser \ IdeUserV2 \ Cache] "LastProfileVersion" = DWORD: 10b8260a

и

[HKEY_USERS \ S-1-5-21-1787888774-1556370510-3519259403-1001 \ Software \ Microsoft \ VSCommon \ брелок] "TokenStorageNameSpace" = "VisualStudio"

[HKEY_USERS \ S-1-5-21-1787888774-1556370510-3519259403-1001 \ Software \ Microsoft \ VsHub \ ServiceModules \ Settings \ PerHubName \ vshub \ ConnectedUser \ IdeUserV2 \ Cache] "LastProfileVersion" = DWORD: 10b8260a

Может быть, где-то есть ключ к этим зашифрованным SessionTokens.json и IdentityServiceAdalCache.cache файлам, но хранение данных в шестнадцатеричном формате усложняет задачу.

Я должен отказаться от этого, почти нет шансов, что я смогу перепроектировать систему аутентификации.

Поставщик учетных данных Visual Studio

NuGet Client SDK решает мою проблему, но фактически не отвечает на этот SO вопрос.

Как я уже говорил, я пытался дозвониться

var componentModel = await ServiceProvider.GetGlobalServiceAsync(typeof(SComponentModel)) as IComponentModel;
componentModel.GetService<ICredentialServiceProvider>()

Но это не сработало, поэтому, если кто-нибудь знает, как получить доступ к поставщику учетных данных Visual Studio, я был бы очень рад узнать ответ.

...