c# - C# 可以写入但不能读取存储库的 BitBucket API
问题描述
我正在尝试使用 C# 访问 BitBucket API。我可以执行一些操作,但不能执行其他操作。值得注意的是,写入存储库是可行的,但读取它们却不行。
using System.Net;
using System.Collections.Specialized;
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; // TLS v1.2 only
var client = new WebClient()
{
Credentials = new NetworkCredential("user", "app_password"),
BaseAddress = "https://api.bitbucket.org",
};
client.DownloadString(
"/2.0/repositories/friendly_private_account/repo"); // 403 Forbidden
client.DownloadString(
"/2.0/repositories/friendly_private_account/repo/src"); // 403 Forbidden
client.UploadValues(
"/2.0/repositories/friendly_private_account/repo/src",
new NameValueCollection() {
{ "/bb.txt", "here is\nsome content\n" },
{ "message", "Commit from API, called with C# WebClient" },
}); // Creates a commit! What!?
这有点奇怪,因为如果您在创建应用程序密码时read
启用权限,您会自动获得权限。write
也不是问题DownloadString()
。如果 App Password 有webhook
权限,则可以读取 Web Hooks。
client.DownloadString(
"/2.0/repositories/friendly_private_account/repo/hooks");
// {"pagelen": 10, "values": [{ … }]}
有趣的是,curl
使用相同的凭据没有任何问题。
$ curl --user "${user}:${app_password}" \
--url "https://api.bitbucket.org/2.0/repositories/friendly_private_account/repo"
# {"scm": "git", "website": "", "has_wiki": false, … }
运行curl
with--verbose
实际上将返回描述您的凭据具有哪些权限以及需要哪些权限的标头。在上面的示例中,它需要repository
,而我有repository:write
。它没有说我有repository:read
,但请求仍然成功。
解决方案
听起来WebClient
只有当服务器以. Authorization
_401 Unauthorized
也许 BitBucket 在某些未经身份验证的端点上以 401 响应,从而引发WebClient
重新发送具有身份验证的请求;但在其他人身上返回 403,立即结束请求。
显式添加Authorization
标题可以解决问题,尽管有点难看。
using System.Net;
using System.Collections.Specialized;
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; // TLS v1.2 only
var client = new WebClient()
{
// Credentials = new NetworkCredential("user", "app_password"), // Take this line out
BaseAddress = "https://api.bitbucket.org",
};
client.Headers[HttpRequestHeader.Authorization] =
"Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes("user:app_password"));
client.DownloadString(
"/2.0/repositories/friendly_private_account/repo"); // Now it works
推荐阅读
- c - 位图文件的像素数据错误
- python - 将字符串转换为日期和时间值
- postgresql - 在 Sqlalchemy 中查询格式不正确以进行选择
- ios - WebRTC 音频无法在使用 CallKit 的锁定屏幕中工作
- python - 如何使用 discord.py 限制机器人在某些频道中响应?
- sql - 计算 TEXT[] 中的元素个数
- php - 通过链接将变量发送到控制器 laravel [更新 - 已修复]
- python - 如何使用 df.to_sql 并将具有两个索引的数据导出到 SQL Server 中的表?
- python - 尽管 CPU 空闲,女服务员还是很慢
- asp.net - Azure 管道 YAML - 安装项目 nuget 包