【发布时间】:2011-11-27 23:50:06
【问题描述】:
我正在尝试从安装服务器的域外部以编程方式访问我的 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/tfs 或http://<serverip>:8080/tfs 的形式(均经过测试,主机文件为最新),这是在 TFS 服务器上设置为通知 URL 的内容。该程序在域内运行。
DifferentKindOfUsernames 是 'DOMAIN\Username'、'LocallyDuplicatedUsername'、'LOCALMACHINE\Username' 中的任何内容,并具有适当的密码,域和计算机上的密码相同。
这个简单的访问在域外不起作用,我有这个错误:
TF30063: You are not authorized to access <serverUri>
在 web 上下文中翻译(在 asp.net 网站中使用相同的过程),这是一个 401 错误:
The remote server returned an error: (401) Unauthorized.
即使(到目前为止测试的东西):
- 我在域外计算机上运行程序的本地用户/密码与对 TFS 具有管理员访问权限的活动目录帐户之间有一个映射(即使已激活 TFS 的模拟权限)。
- 我添加了一个
BackConnectionNames注册表项,其中包含域外部机器名称和 ip,如 here 所述。 - 我禁用了环回检查,如 here 所述。
- 我使用具有不同用户/域或计算机名称组合的 Active Directory 模拟程序。 Active Directory Impersonator 被描述为here。
- 我在域外部服务器 IE 安全选项中将 TFS 服务器 IP 添加到本地 Internet 区域(也尝试过受信任的站点),如 here 所述。
我已经测试了从浏览器对 serverURI 的访问。如果我使用 DomainName\User + Password 提供凭据,则 uri 有效,并且我可以访问 TFS 集合。在我之前描述的任何修改之前,我对此进行了测试。除了我迄今为止测试过的所有内容之外,我想知道编程访问和浏览器访问之间可能有什么区别。
【问题讨论】:
-
您仍然无法从当前运行此代码的计算机访问 TFS 服务器。您需要检查 TFS 中的任何其他安全/权限设置。我不认为这是一个编程问题。
-
@SpikeX :我可以从机器访问 TFS 服务器。我打开了所需的端口,并可以通过 Web 浏览器使用与 Impersonator 相同的凭据访问 URI。如果 Web 客户端工作正常,我希望我的程序也能做同样的事情,但事实并非如此。如果我的程序能够连接,我可以看到它应该检索的信息(集合和项目列表)。我可以看到为什么编程错误(缺少或错误的凭据初始化)和网络/服务器错误(配置问题)之间模糊不清。
-
那么我的下一个愚蠢的问题是,你的 URI 包含
http://和一个端口号,对吗? -
确实如此:http://
:8080/tfs。即使在主机文件中设置了服务器名称,我也尝试使用 ip。如果我在域内,该程序可以完美运行。如果这个问题没有编程解决方案,我正在考虑尝试 RODC (technet.microsoft.com/en-us/library/cc732801(WS.10).aspx),然后我会将这个问题迁移到服务器故障。但是我必须缺少一些东西才能让程序在非域机器上像 webclient 一样工作。 -
你试过没有
/tfs吗?我这里连接到 Intranet 服务器的 TFS 代码没有那个(库可能会自动添加它)。
标签: c# active-directory impersonation tfs-sdk