以编程方式从域外访问TFS 2010

Mat*_*ieu 6 c# impersonation active-directory tfs-sdk tfs2010

我正在尝试以编程方式从安装服务器的域外部访问我的TFS服务器.基本测试程序如下所示:

class Program
    {
        static void Main(string[] args)
        {
            Uri tfsUri = new Uri("<serverUri>");
            TfsConfigurationServer _ConfigurationServer = TfsConfigurationServerFactory.GetConfigurationServer(tfsUri);
            CatalogNode projectCollectionCatalog = _ConfigurationServer.CatalogNode.QueryChildren(new[] { CatalogResourceTypes.ProjectCollection }, false, CatalogQueryOptions.None)[0]; // actual connection tries to happen here
        }
    }
Run Code Online (Sandbox Code Playgroud)

另一个版本,强制凭据:

 class Program
    {
        static void Main(string[] args)
        {
            Uri tfsUri = new Uri("<serverURI>");
            TfsConfigurationServer _ConfigurationServer = new TfsConfigurationServer(tfsUri, new NetworkCredential("<DifferentKindOfUsernames>", "<Password>"));
            CatalogNode projectCollectionCatalog = _ConfigurationServer.CatalogNode.QueryChildren(new[] { CatalogResourceTypes.ProjectCollection }, false, CatalogQueryOptions.None)[0];
        }
    }
Run Code Online (Sandbox Code Playgroud)

另一个版本混合了以前的版本:

public class ConnectByImplementingCredentialsProvider : ICredentialsProvider
    {
        public ICredentials GetCredentials(Uri uri, ICredentials iCredentials)
        {
            return new NetworkCredential("<DifferentKindOfUsernames>", "<Password>", "<DomainOrNot>");
        }

        public void NotifyCredentialsAuthenticated(Uri uri)
        {
            throw new ApplicationException("Unable to authenticate");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string _myUri = @"<serverUri>";

            ConnectByImplementingCredentialsProvider connect = new ConnectByImplementingCredentialsProvider();
            ICredentials iCred = new NetworkCredential("<DifferentKindOfUsernames>", "<Password>", "<DomainOrNot>");
            connect.GetCredentials(new Uri(_myUri), iCred);

            TfsConfigurationServer configurationServer =
                               TfsConfigurationServerFactory.GetConfigurationServer(new Uri(_myUri), connect);
            configurationServer.EnsureAuthenticated();


        }
    }
Run Code Online (Sandbox Code Playgroud)

还有一个带有活动目录Impersonator的版本:

class Program
    {
        static void Main(string[] args)
        {
            using (new Impersonator("<DifferentKindOfUsernames>", "<DomainOrNot>", "<Password>"))
            {
               Uri tfsUri = new Uri("<serverUri>");
               TfsConfigurationServer _ConfigurationServer = TfsConfigurationServerFactory.GetConfigurationServer(tfsUri);
               CatalogNode projectCollectionCatalog = _ConfigurationServer.CatalogNode.QueryChildren(new[] { CatalogResourceTypes.ProjectCollection }, false, CatalogQueryOptions.None)[0]; // actual connection tries to happen here
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

serverURIhttp://<servername>:8080/tfs或者http://<serverip>:8080/tfs(都经过测试,主机文件是最新的)的形式,这是在TFS服务器上设置为通知URL的.该程序在域内工作.

DifferentKindOfUsernames 来自'DOMAIN\Username','LocallyDuplicatedUsername','LOCALMACHINE\Username'以及相应的密码,密码在域和机器上是相同的.

这个简单的访问不会在域外工作,我有这个错误:

TF30063: You are not authorized to access <serverUri>
Run Code Online (Sandbox Code Playgroud)

在Web上下文中翻译(在asp.net网站上使用相同的过程),这是一个401错误:

The remote server returned an error: (401) Unauthorized.
Run Code Online (Sandbox Code Playgroud)

即使(到目前为止测试的东西):

  • 我在域外部机器上运行程序的本地用户/密码与对TFS具有管理访问权限的活动目录帐户之间存在映射(即使已激活TFS的模拟权限).
  • 我添加BackConnectionNames注册表项与域局外人机器名和IP等中描述的在这里.
  • 我禁用了这里描述的环回检查.
  • 我使用具有不同用户/域或计算机名称组合的Active Directory模拟器.此处描述 Active Directory模拟器.
  • 我加入了TFS服务器IP来像描述的域服务器外人IE的安全选项的本地互联网区(试过受信任的站点以及)在这里.

我已经测试了从浏览器访问serverURI的情况.如果我使用DomainName\User + Password提供凭据,uri可以工作,我可以访问TFS Collection.我在之前描述的任何修改之前测试了这个.我想知道除了我到目前为止测试过的所有内容之外,程序访问和浏览器访问之间的区别是什么.

Edw*_*son 4

您没有传递凭据来建立连接。这意味着您正在使用当前从域外部的主机登录的凭据。我不是 Windows 身份验证方面的专家,但我认为在某些情况下,这可以透明地工作(如果用户名和密码相同),但它似乎取决于所使用的 NTLM 版本、客户端和服务器操作系统、信任关系和安全区域、IIS 配置,或许还有月相。

换句话说,您可能希望将凭据传递给连接:

TfsConfigurationServer _ConfigurationServer = new TfsConfigurationServer(uri, new NetworkCredential("username", "password", "DOMAIN"));
Run Code Online (Sandbox Code Playgroud)

请注意,如果您通过不受信任的(公共)网络连接到服务器,强烈建议启用 SSL/TLS。

(我更正了这一点,使用 NetworkCredential 的三参数构造函数——我的错误。正如您所注意到的,如果您将DOMAIN\username用户名参数放入 NetworkCredential,它会将其视为而\DOMAIN\username不是DOMAIN\username。我想,这就是为什么没有人让我编写 C# 代码。)