上文http://m.itdecent.cn/p/a0d77b0b4809我們通過調用Sonar的API接口實現(xiàn)了對掃描結果獲取,并通過一個計算模型完成對整個發(fā)布流的質量控制
但我們實際用的過程發(fā)現(xiàn)如下問題:
1.上文中接口調用沒有傳遞任何口令但也能成功調用,原因是我們Sonar建的項目是公開的。
2.用戶創(chuàng)建及項目創(chuàng)建工作繁瑣,沒有與內部的項目管理軟件打通。
本文我們通過對Api的進一步驗證解決這些問題。
1.Sonar Api說明
Sonar的Api一些主要問題,提前列出,避免入坑
1.Sonar的Api各版本差異較大,向下兼容性差
2.Sonar的Api不是很人性化,其Post的接口,參數(shù)不是寫body中,而是寫URL中。
3.當接口返回400/404時通常是你接口參數(shù)錯了,并不能簡單理解為接口地址不存在,而是應該先檢查參數(shù)值,對api講大概率是數(shù)據(jù)不存在。
4.文檔是描述接口參數(shù)有時候有多個(如projectId/projectKey),很多是二選一的,全部提供了反而報錯。
2.Sonar的Api安全
sonar的api調用是可以添加token的,接口是否需要token是根據(jù)要操作的接口的權限決定,有些接口強制需要token,具體可參考其api頁面介紹。
Token模式
sonar的token是使用Basic Authorization認證,調用接口時在http header中添加如下信息:
header.Add("Authorization", "Basic " + basicToken);
其中值的格式是 Basic空格+token
token的格式是將 登錄帳戶:密碼 進行Base64加密(UTF-8格式)
示例代碼.netCore版本
public Dictionary<string, string> GetAuthHeader()
{
Dictionary<string, string> header = new Dictionary<string, string>();
string basicToken = EncodeBase64("admin:123456"); //帳戶:密碼
header.Add("Authorization", "Basic " + basicToken);
return header;
}
public static string EncodeBase64(string code, string code_type = "UTF-8")
{
string encode = "";
byte[] bytes = Encoding.GetEncoding(code_type).GetBytes(code);
try
{
encode = Convert.ToBase64String(bytes);
}
catch
{
encode = code;
}
return encode;
}
示例代碼Java版本
String encodedText = encoder.encodeToString("admin:adssmin".getBytes("UTF-8"));
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Authorization", "Basic " + encodedText);
3.Sonar的常用Api擴展封裝參考
創(chuàng)建項目
public string CreateProject(string name, string project)
{
//默認寫死了private
string postData = string.Format("name={0}&project={1}&visibility=private", name, project);
string url = sonarRootUrl + "/api/projects/create?" + postData;
Dictionary<string, string> header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, "", "application/json", header);
return result;
}
刪除項目
public string DeleteProject(string project)
{
string postData = string.Format("project={0}", project);
string url = sonarRootUrl + "/api/projects/delete?" + postData;
Dictionary<string, string> header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, "", "application/json", header);
return result;
}
為用戶授權指定項目特定權限
/// <summary>
/// 為用戶授權指定項目權限
/// </summary>
/// <param name="userId">用戶帳戶</param>
/// <param name="project">project Key</param>
/// <param name="permision">權限:admin, codeviewer, issueadmin, securityhotspotadmin, scan, user</param>
/// <returns></returns>
public string AddUserToProject(string userId, string permision, string projectKey)
{
//參數(shù)projectId與projectKey二選一,不要全部寫上,建議用key,projectId需要庫中找
//權限等級admin, codeviewer, issueadmin, securityhotspotadmin, scan, user (對應界面瀏覽)
//不能批量授予多個權限,如果要授權codeviewer和scan兩個權限,則需要分多次調用該接口。
string postData = string.Format("login={0}&permission={1}&projectKey={2}", userId, permision, projectKey);
string url = sonarRootUrl + "/api/permissions/add_user?" + postData;
Dictionary<string, string> header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, "", "application/json", header);
return result;
}
移除用戶在指定項目中權限
public string RemoveUserToProject(string userId, string permision, string projectKey)
{
string postData = string.Format("login={0}&permission={1}&projectKey={2}", userId, permision, projectKey);
string url = sonarRootUrl + "/api/permissions/remove_user?" + postData;
Dictionary<string, string> header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, "", "application/json", header);
return result;
}
創(chuàng)建用戶并生成Token
public string CreateUserWithToken(string userId, string mail, string userName)
{
string output = "";
string postData = string.Format("mail={0}&local=false&login={1}&name={2}", mail, userId, userName);
string url = sonarRootUrl + "/api/users/create?" + postData;
Dictionary<string, string> header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, "", "application/json", header);
LogHelper.Debug("CreateUserResult:" + result);
output += result;
postData = string.Format("login={0}&name=myToken", userId);
url = sonarRootUrl + "/api/user_tokens/generate?" + postData;
result = HttpHelper.HttpPost(url, postData, "application/json", header);
LogHelper.Debug("CreateUserTokenResult:" + result);
output += result;
result = AddUserToGroup(userId);
output += result;
//這里偷了個懶沒有對結果處理,你可以將數(shù)據(jù)提取整理成對接方真正需要的數(shù)據(jù)結構。
return output;
}
添加用戶到群組
/// <summary>
/// 添加用戶到默認組中
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public string AddUserToGroup(string userId, string groupName = "")
{
if (string.IsNullOrEmpty(groupName)) groupName = "defaultGroup";
//如果用id需要去數(shù)據(jù)庫group表看。URL中id與name二選1即可,建議用name。id=3&login={0} name=myDefaultGroup
string postData = string.Format("name={0}&login={1}", groupName, userId);
string url = sonarRootUrl + "/api/user_groups/add_user?" + postData;
Dictionary<string, string> header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, postData, "application/json", header);
LogHelper.Debug("AddGroupResult:" + result);
return result;
}
移除用戶從指定群組
/// <summary>
/// 將用戶從組中移除
/// </summary>
/// <param name="userId"></param>
/// <param name="groupName"></param>
/// <returns></returns>
public string RemoveToGroup(string userId, string groupName = "")
{
if (string.IsNullOrEmpty(groupName)) groupName = "defaultGroup";
string postData = string.Format("name={0}&login={1}", groupName, userId);
string url = sonarRootUrl + "/api/user_groups/remove_user?" + postData;
Dictionary<string, string> header = GetAuthHeader();
string result = HttpHelper.HttpPost(url, postData, "application/json", header);
return result;
}