JIRA Rest API使用C#登录

15

我写了以下的C#代码来登录到JIRA Rest API:

var url = new Uri("http://localhost:8090/rest/auth/latest/session?os_username=tempusername&os_password=temppwd");
var request = WebRequest.Create(url) as HttpWebRequest;
if (null == request)
{
 return "";
}
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength = 200;
request.KeepAlive = false;
using (var response = request.GetResponse() as HttpWebResponse)
{
}
当我执行这段代码时,应用程序会一直运行而没有返回任何响应。请建议是否使用REST API正确调用JIRA登录。

你为什么指定了ContentType和ContentLength?我在你的代码中没有看到任何实际的内容/正文。 - Pete
你说返回没有任何响应,那么你的request.GetResponse()是否会抛出异常?网络服务器应该至少有某种响应。 - user45886
6个回答

36

要进行基本身份验证,您需要将用户名和密码以base64编码的形式发送。在Atlassian开发者页面的API示例中可以找到相关指南: https://developer.atlassian.com/display/JIRADEV/JIRA+REST+API+Example+-+Basic+Authentication 如果您在使用C#语言,请按以下格式将编码后的数据作为头信息发送:

"Authorization: Basic [ENCODED CREDENTIALS]"

以下是一个简单的示例:

public enum JiraResource
{
    project
}

protected string RunQuery(
    JiraResource resource, 
    string argument = null, 
    string data = null,
    string method = "GET")
{
    string url = string.Format("{0}{1}/", m_BaseUrl, resource.ToString());

    if (argument != null)
    {
        url = string.Format("{0}{1}/", url, argument);
    }

    HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
    request.ContentType = "application/json";
    request.Method = method;

    if (data != null)
    {
        using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
        {
            writer.Write(data);
        }
    }

    string base64Credentials = GetEncodedCredentials();
    request.Headers.Add("Authorization", "Basic " + base64Credentials);

    HttpWebResponse response = request.GetResponse() as HttpWebResponse;

    string result = string.Empty;
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
        result = reader.ReadToEnd();
    }

    return result;
}

private string GetEncodedCredentials()
{
    string mergedCredentials = string.Format("{0}:{1}", m_Username, m_Password);
    byte[] byteCredentials = UTF8Encoding.UTF8.GetBytes(mergedCredentials);
    return Convert.ToBase64String(byteCredentials);
}

(JiraResource只是我用来决定使用API的哪个部分的枚举)

希望这能帮到你!


如果您尝试使用WCF服务进行连接,则此解决方案将无法正常工作。 - AskMe
这篇帖子建议在写入前添加授权头,这可能是有道理的。不幸的是,这个解决方案没有解决我的401问题。 - B5A7

6

这里提供了一个更简单的解决方案,符合要求:

var mergedCredentials = string.Format("{0}:{1}", username, password);
var byteCredentials = Encoding.UTF8.GetBytes(mergedCredentials);
var encodedCredentials = Convert.ToBase64String(byteCredentials);

using (WebClient webClient = new WebClient())
{
    webClient.Headers.Set("Authorization", "Basic " + encodedCredentials);

    return webClient.DownloadString(url);
}

2
如果您不想在每个请求中编码凭据,可以使用cookies来实现。在请求cookie时,无需在标头中添加任何授权信息。此方法将接受一个包含用户名、密码和URL的JSON字符串,并返回cookie值。
public async Task<JiraCookie> GetCookieAsync(string myJsonUserNamePassword, string JiraCookieEndpointUrl)
{
    using (var client = new HttpClient())
        {
            var response = await client.PostAsync(
                JiraCookieEndpointUrl,
                new StringContent(myJsonUserNamePassword, Encoding.UTF8, "application/json"));
            var json = response.Content.ReadAsStringAsync().Result;
                var jiraCookie= JsonConvert.DeserializeObject<JiraCookie>(json);
                return jArr;
         }
}

public class JiraCookie
{
    public Session session { get; set; }
}

public class Session
{
    public string name { get; set; }
    public string value { get; set; }
}

当我使用以下URL进行调用:http://[baseJiraUrl]/rest/auth/1/session,它会返回以下JSON响应:
{
"session" : -{
"name" : JSESSIONID,
"value" : cookieValue
}

请记住,上面的URL在我使用的JIRA版本中是有效的,根据您使用的版本可能会有所不同。阅读JIRA API文档以获取您正在使用的正确URL。我正在使用以下内容: https://docs.atlassian.com/software/jira/docs/api/REST/7.6.1/#auth/1/session 请记住,您需要存储cookie并在每个后续请求中使用它。 查看此答案以了解如何将cookie添加到您的HttpClient请求中: How do I set a cookie on HttpClient's HttpRequestMessage
一旦您完成cookie(注销),只需发送一个带有与post相同的URL的delete http请求即可。

0
我调整了RunQuery代码,使其可以在今天(2018年4月)运行。下面引用的加密/解密来自以下链接(我将其转换为扩展方法并将值放入环境中)。

https://dev59.com/fGkw5IYBdhLWcg3wDWTL

我成功地执行了来自LinqPad的代码 - 因此在RunQuery之后使用Dump()命令

private string _baseUrl = "https://xxxxxx.atlassian.net";
private string _username = "YourLogin";

void Main()
{
    RunQuery(JiraResource.project).JsonToXml().Dump();
}

public enum JiraResource { project }

private const string restApiVersion = "/rest/api/2/";

protected string RunQuery(  JiraResource resource,  string argument = null, string data = null, string method = "GET")
{
    string url = $"{_baseUrl}{restApiVersion}{resource}";

    if (argument != null) url = $"{url}{argument}/";

    var request = WebRequest.Create(url) as HttpWebRequest;
    request.ContentType = "application/json";
    request.Method = method;

    if (data != null)
    {
        using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
        {
            writer.Write(data);
        }
    }
    string base64Credentials = GetEncodedCredentials();
    request.Headers.Add("Authorization", "Basic " + base64Credentials);

    var response = request.GetResponse() as HttpWebResponse;
    string result = string.Empty;
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
        result = reader.ReadToEnd();
    }
    return result;
}

private string GetEncodedCredentials()
{
    var encryptedPassword = Environment.GetEnvironmentVariable("PassEncrypted");
    var encryptionSalt = Environment.GetEnvironmentVariable("PassSalt");
    var password = encryptedPassword.Decrypt(encryptionSalt);

    var mergedCredentials = $"{_username}:{password}";
    var byteCredentials = UTF8Encoding.UTF8.GetBytes(mergedCredentials);
    return Convert.ToBase64String(byteCredentials);
}

public static class MyExtensions
{
    public static XElement JsonToXml(this string jsonData, bool isAddingHeader = true)
    {
        var data = isAddingHeader
            ? "{\"record\":" + jsonData + "}"
            : jsonData;

        data = data // Complains if xml element name starts numeric
            .Replace("16x16", "n16x16")
            .Replace("24x24", "n24x24")
            .Replace("32x32", "n32x32")
            .Replace("48x48", "n48x48");

        var result = JsonConvert.DeserializeXmlNode(data, "data");
        var xmlResult = XElement.Parse(result.OuterXml);
        return xmlResult;
    }
}

0
static void Main(string[] args)
{
    using (WebClient wc = new WebClient())
    {
        wc.Headers.Add("Authorization", "Basic " + GetEncodedCredentials());

        string tasks = wc.DownloadString("yourjiraurl/search?jql=task=bug");
        var taskdetails = JsonConvert.DeserializeObject<TaskDetails>(tasks);
    }
}

static string GetEncodedCredentials()
{
    string mergedCredentials = string.Format("{0}:{1}", "UserName", "Password");
    byte[] byteCredentials = UTF8Encoding.UTF8.GetBytes(mergedCredentials);
    return Convert.ToBase64String(byteCredentials);
}

0

在 Rest 中发布多部分内容,我使用 Tiny.RestClient

var client = new TinyRestClient(new HttpClient(), "http://localhost:8090");

var strResult = await client.PostRequest("rest/auth/latest/session).
WithBasicAuthentication("username", "password")
ExecuteAsStringAsync();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接