6

我正在尝试从安装服务器的域外部以编程方式访问我的 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
        }
    }

另一个版本,强制使用凭据:

 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];
        }
    }

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

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();


        }
    }

还有一个带有活动目录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
            }
        }
    }

serverURI采用http://<servername>:8080/tfshttp://<serverip>:8080/tfs(均经过测试,主机文件为最新)的形式,这是在 TFS 服务器上设置为通知 URL 的内容。该程序在域内工作。

DifferentKindOfUsernames来自 'DOMAIN\Username'、'LocallyDuplicatedUsername'、'LOCALMACHINE\Username' 的任何内容,并具有适当的密码,域和机器上的密码相同。

这种简单的访问在域之外不起作用,我有这个错误:

TF30063: You are not authorized to access <serverUri>

在网络环境中翻译(在 asp.net 网站中使用相同的过程),这是一个 401 错误:

The remote server returned an error: (401) Unauthorized.

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

  • 我在域外机器上运行程序的本地用户/密码与对 TFS 具有管理员访问权限的活动目录帐户之间有一个映射(即使已激活 TFS 的模拟权限)。
  • 我添加了一个BackConnectionNames带有域外机器名称和 ip 的注册表项,如下所述
  • 我禁用了这里描述的环回检查。
  • 我使用具有不同用户/域或机器名称组合的 Active Directory Impersonator。此处描述的 Active Directory 模仿者。
  • 我在域外服务器 IE 安全选项中将 TFS 服务器 IP 添加到本地 Internet 区域(也尝试过受信任的站点),如此处所述

我已经测试了从浏览器对 serverURI 的访问。如果我使用 DomainName\User + Password 提供凭据,则 uri 有效,并且我可以访问 TFS 集合。在我之前描述的任何修改之前,我对此进行了测试。除了我迄今为止测试过的所有内容之外,我想知道编程访问和浏览器访问之间可能有什么区别。

4

1 回答 1

4

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

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

TfsConfigurationServer _ConfigurationServer = new TfsConfigurationServer(uri, new NetworkCredential("username", "password", "DOMAIN"));

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

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

于 2011-09-29T20:50:40.460 回答