Teamcity REST API问题与POST方法



我正在尝试从。net Core创建一个TeamCity项目。我已经写了下面的代码,但当我试图运行代码时,我得到一个错误。

代码:

public void CreateProject(string name, string newProjectId, string parentProjectId)
{
InvokeTeamCityApi(() => _apiClient.CreateProject(new NewProjectDescription
{
Name = name,
Id = newProjectId,
SourceProject = new GetProjectResponse
{
Id = _toolContext.HostingContext.TeamCityProjectTemplate
},
ParentProject = new GetProjectResponse
{
Id = parentProjectId
},
CopyAllAssociatedSettings = true,
}));
}

错误:

403 Forbidden: CSRF报头X-TC-CSRF-Token不匹配CSRF会话值

我也做了一个谷歌搜索,我试着添加头原点,但我没有访问权限禁用内部teamcity属性来禁用CSRF检查。

所以我在请求中传递令牌X-tc-CSRF-Token,但它说值不匹配。如何解决这个问题?

注意:只有当我使用不记名令牌并且具有基本权限时,它才能正常工作时,我才会遇到此问题。

我最近在从TeamCity 10升级到TeamCity 2022时遇到了同样的问题,并最终设法找出了如何解决它。重要的是,我不需要访问内部TeamCity属性来禁用CSRF检查,因为我认为拥有额外的安全层并不是一件坏事。

可能是重要的东西,我改变了:

  • 我为我用来访问REST API的帐户生成了一个访问令牌,这样我就不需要把我的密码放在代码中。访问令牌可以与比您自己的帐户更严格的权限相关联。

  • 使用HttpClient,授权是通过添加一个默认头(通过DefaultHeaders属性)来实现的,名称为"Authorization",值为"Bearer {apiToken}"

  • 我读取/authenticationTest.html?csrf端点以获得CSRF令牌,然后将该值添加为默认标头("X-TC-CSRF-Token")。也可以用同样的方式使用"tc-csrf-token"头。

请注意,因为"Authorization""X-TC-CSRF-Token"/"tc-csrf-token"标头是作为默认标头添加的,所以不需要在每个HTTP (GET, POST,DELETE等)方法上显式地执行此操作。


下面是一些示例代码,涵盖了上述所有内容。

public class Sample
{
private readonly string _baseUrl;
private readonly HttpClient _httpClient = new HttpClient();
public Sample(string baseUrl, string accessToken)
{
_baseUrl = baseUrl;
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
var csrfToken = get("/authenticationTest.html?csrf");
_httpClient.DefaultRequestHeaders.Add("X-TC-CSRF-Token", csrfToken);
}
public void CreateProject(string id, string name)
{
post("/app/rest/projects", $"<newProjectDescription id="{id}" name="{name}" />");
}
private string get(string relativeUrl)
{
var getTask = _httpClient.GetAsync(_baseUrl + relativeUrl);
getTask.Wait();
var response = getTask.Result;
response.EnsureSuccessStatusCode();
var readTask = response.Content.ReadAsStreamAsync();
readTask.Wait();
using ( var stream = readTask.Result )
using ( var reader = new StreamReader(stream) )
return reader.ReadToEnd();
}
private void post(string relativeUrl, string data)
{
using ( var content = new StringContent(data, Encoding.UTF8, "application/xml") )
{
var postTask = _httpClient.PostAsync(_baseUrl + relativeUrl, content);
postTask.Wait();
var response = postTask.Result;
response.EnsureSuccessStatusCode();
var readTask = response.Content.ReadAsStreamAsync();
readTask.Wait();
}
}
}

使用,例如

// Change these according to your situation
var baseUrl = "http://localhost:8111";
var accessToken = "1234567890";
var sample = new Sample(baseUrl, accessToken);
sample.CreateProject("ProjectID", "ProjectName");

请注意,这只是一个让您站稳脚跟的示例:我通过在代码中采用各种快捷方式来保持代码简短(例如,HttpClient实际上应该是应用程序的一个静态HttpClient:参见learn.microsoft.com上使用HttpClient的指南)。

最新更新