在 VSIX 项目中获取存储在 Visual Studio 某处的 Nuget 凭据 [英] Get Nuget credentials stored somewhere by Visual Studio in a VSIX project

查看:31
本文介绍了在 VSIX 项目中获取存储在 Visual Studio 某处的 Nuget 凭据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个需要管理给定项目的 Nuget 包的 Visual Studio 扩展(VSIX 项目).

I'm developing a Visual Studio extension (VSIX project) that needs to manage Nuget packages of a given project.

我已经将 IVsPackageInstaller 服务用作 此处记录,但这是有限的,我需要更多功能(例如获取给定包的最新版本号).

I'm already using the IVsPackageInstaller service as documented here but this is limited and I need more features (for example get the latest version number of a given package).

我搜索了但没有找到任何关于如何以编程方式与 Visual Studio 包管理器交互的信息,所以我决定直接使用 Nuget API.

I searched but didn't find anything on how to programmatically interact with the Visual Studio Package Manager so I decided to go for the Nuget API directly.

我使用 WebRequest 类向 Nuget API 发送 HTTP 请求(因为我们不能在 VSIX 项目中使用 HttpClient),但我遇到了一个问题:请求将发送到需要身份验证的私有 Nuget 提要!(托管在 Azure DevOps 上)

I send HTTP requests to the Nuget API using the WebRequest class (because we can't use HttpClient in a VSIX project) but I'm hitting a problem: the requests are going to a private Nuget feed that needs authentication! (hosted on Azure DevOps)

我使用 Fiddler 来检查发送到我们 Azure DevOps 服务器的 HTTP 请求.我看到一个 POST 请求发送到 https://app.vssps.visualstudio.com/_apis/Token/SessionTokens 并带有一个令牌作为响应,但这不是我正在寻找的令牌.

I used Fiddler to check the HTTP requests sent to our Azure DevOps server. I see a POST request going to https://app.vssps.visualstudio.com/_apis/Token/SessionTokens with a token in response but this is not the Token I'm looking for.

传递给 Nuget API 的令牌是一个 Basic 令牌,不知从何而来.我在捕获的 HTTP 响应中找不到此令牌.

The token passed to the Nuget API is a Basic token that comes from I don't know where. I couldn't find this token anywhere in the HTTP responses I caught.

我还可以看到对我们 Azure DevOps 服务器的一些响应包含一些这样的标头(我更改了 GUID)

I can also see that some responses to our Azure DevOps server contain some headers like this (I changed the GUID)

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

我可以在 %userprofile%\AppData\Local\.IdentityService\AccountStore.json 文件中找到这个 GUID,这里肯定有问题.同一文件夹中的 SessionTokens.json 文件看起来也很有趣,但它是加密的...

I can find this GUID back in the %userprofile%\AppData\Local\.IdentityService\AccountStore.json file, there is definitely something going on here. And the SessionTokens.json file in the same folder looks reeeaaally interesting too but it's encrypted...

我还尝试在注册表中挖掘是否可以找到有趣的信息,例如在 西蒙的评论 但似乎 VS2017 不再在那里存储令牌.

I also tried to dig in the Registry to see if I can find interesting information for example at the path specified in Simon's comment but it seems VS2017 doesn't store the token there anymore.

我还加载了 privateregistry.bin 文件(又名 Visual Studio Settings Store)并到处搜索,但找不到任何东西.

I also loaded the privateregistry.bin file (aka the Visual Studio Settings Store) and searched everywhere but couldn't find anything.

因此,我不想尝试对 Visual Studio 进行逆向工程,而是想直接访问其凭据提供程序.我尝试访问多个服务和课程

So instead of trying to reverse engineer Visual Studio I wanted to access its Credential Provider directly. I tried to access to several services and classes

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

但它们都不起作用(返回 null 或异常).

But none of them are working (return null or Exception).

我在 NuGet 中徘徊.PackageManagement.VisualStudio 项目在 Github 上,但找不到我的答案.

I wandered in the NuGet.PackageManagement.VisualStudio project on Github but couldn't find my answer.

还有许多 Nuget 包,例如 NuGet.PackageManagement.VisualStudioMicrosoft.VisualStudio.Services.Release.ClientMicrosoft.VisualStudio.Services.ExtensionManagement.WebApiMicrosoft.VisualStudio.Services.InteractiveClient 仅举几例,但老实说我不知道​​我要找的东西是否在那里...

There are also many Nuget packages like NuGet.PackageManagement.VisualStudio, Microsoft.VisualStudio.Services.Release.Client, Microsoft.VisualStudio.Services.ExtensionManagement.WebApi, Microsoft.VisualStudio.Services.InteractiveClient just to name a few but honestly I don't know if what I'm looking for is there...

那么如何访问 Visual Studio 使用的 Nuget 凭据呢?

So how to access the Nuget credentials used by Visual Studio?

我采用任何可以让我访问所有读取 Nuget 功能的解决方案,例如以编程方式使用 Visual Studio 包管理,或解密此 SessionTokens.json 文件或访问 Visual Studio Credential Provider.

I take any solution that gives me access to all the reading Nuget features, for example programmatically use the Visual Studio Package Management, or decrypt this SessionTokens.json file or access the Visual Studio Credential Provider.

答案越少hacky,当然就越好.

The less hacky is the answer, the better it is of couse.

此时您可能已经猜到了,我不想自己将 usernamepassword 存储在某个地方.我需要创建一个用户友好的 VS 扩展,这就是为什么我想检索和使用用户已保存在 Visual Studio 中的凭据.

At this point you probably already guessed, I don't want to store the username and password somewhere myself. I need to create a user-friendly VS extension, that's why I want to retrieve and use the credentials already saved in Visual Studio by the users.

如果你能解决这个问题,非常感谢.

Thank you so much if you can solve this problem.

推荐答案

NuGet Client SDK

非常感谢 Simon 为我指明了 NuGet.Client 的方向.

Microsoft 的唯一文档 正在链接2016 年 Dave Glick 的博文,但他们也给一个很好的注释:

The only documentation from Microsoft is linking a 2016 blog post from Dave Glick but they also give a nice note:

这些博文是在 NuGet 客户端 SDK 包的 3.4.3 版本发布后不久撰写的.较新版本的软件包可能与博文中的信息不兼容.

These blog posts were written shortly after the 3.4.3 version of the NuGet client SDK packages were released. Newer versions of the packages may be incompatible with the information in the blog posts.

好的,那么我想我们可以使用 Dave 的博客...

Alright, then I guess we will do with Dave's blog...

您应该安装两个包:NuGet.ClientNuget.Protocol

You should install two packages: NuGet.Client and Nuget.Protocol

然后这里是获取包的最新版本的示例代码:

Then here is the code for example to get the last version of a package:

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 请求中使用的令牌存储到 Nuget API 的位置进行逆向工程.

Physical Token Storage Place

I tried to reverse engineer where Visual Studio was storing the token used in HTTP requests to the Nuget API.

我将注册表的所有不同配置单元导出到文本文件,包括 Visual Studio 设置存储 (privateregistry.bin).然后在 Visual Studio 中添加了一个全新的 Nuget 提要,按预期获得登录弹出窗口,所以我登录了.最后,我再次将所有蜂巢导出为文本文件,并将它们与身份验证前的所有文件进行比较.

I exported to text files all the different hives of the Registry including the Visual Studio Settings Store (privateregistry.bin). Then added a brand new Nuget feed in Visual Studio, got the login popup as expected so I logged in. Finally I exported all the hives again to text files and compared them all with the files before authentication.

我在 VS 设置商店中没有发现任何有趣的东西.

I found nothing interesting in the 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\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_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\Keychain]"TokenStorageNameSpace"="VisualStudio"

[HKEY_USERS\S-1-5-21-1787888774-1556370510-3519259403-1001\Software\Microsoft\VSCommon\Keychain] "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

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

也许在某处,有这些加密的 SessionTokens.jsonIdentityServiceAdalCache.cache 文件的密钥,但以十六进制存储数据会使事情变得更加困难.

Maybe somewhere, there is the key to these encrypted SessionTokens.json and IdentityServiceAdalCache.cache files but having the data stored in hexadecimal makes things even harder.

我必须放弃这个,我几乎不可能对身份验证系统进行逆向工程.

I've to give up on this, almost no chance I could reverse engineer the authentication system.

NuGet Client SDK 解决了我的问题,但实际上并没有回答这个 SO 问题.

The NuGet Client SDK solves my issue but doesn't actually answer to this SO question.

正如我所说,我试着打电话

As I said, I tried to call

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

但这不起作用,所以如果有人知道如何访问 Visual Studio 凭据提供程序,我会很高兴知道答案.

But this didn't work, so if anybody knows how to access the Visual Studio credentials provider, I would be really glad to know the answer.

这篇关于在 VSIX 项目中获取存储在 Visual Studio 某处的 Nuget 凭据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆