Bonita Web API - 401未授权错误
我正在尝试使用Bonita Web API。我的代码如下。正如你所看到的,我在调用任何其他API服务之前调用loginservice。它登录到OK 200.但是,当我进行后续调用以获取进程列表时,出现401错误。您从第一次调用中获得JSESSIONID,并且您想将它传递给后续调用来验证您的身份。Bonita Web API - 401未授权错误
var baseAddress = new Uri(<base address>);
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
HttpResponseMessage result = client.PostAsync("/bonita/loginservice", new StringContent("login=<username>,password=<password>,redirect=false")).Result;
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage result2 = client.GetAsync("/bonita/API/bpm/process").Result;
result2.EnsureSuccessStatusCode();
}
这适用于.Net 2.0 C#,但有一些有趣的事情要检查。
WebClient wc = new WebClient();
wc.Proxy = WebRequest.GetSystemWebProxy();
//wc.Headers[HttpRequestHeader.AcceptEncoding] = "gzip, deflate";
string strLogin = wc.DownloadString("http://localhost:8080/bonita/loginservice?username=walter.bates&password=bpm&redirect=false");
wc.Headers[HttpRequestHeader.Cookie] = wc.ResponseHeaders[HttpResponseHeader.SetCookie].ToString();
string strCookie = wc.ResponseHeaders[HttpResponseHeader.SetCookie].ToString();
string strProcesses = wc.DownloadString("http://localhost:8080/bonita/API/bpm/process?p=0");
首先,你应该知道如何确定所进行的操作是成功(登录,getProcesses和其他)当您尝试登录,你总是会得到头(例如"JSESSIONID=50E509D37AC28E2D725CBD45A8112FA7; Path=/bonita; HttpOnly"
),并确定200即使您在Bonita的登录尝试是不成功的。
对于前面的示例
1)在成功登录,您必须通过强制性的表单数据:用户名,密码和重定向您还必须确保通过重定向小写。 "False"
将不起作用,"false"
将工作。因此,对于.Net
,假设您有一个property-> Boolean
重定向。你必须用redirect.ToString().ToLower()
来使它小写,因为价值将会是"False"
而你不想要。
假设您尝试仅使用用户名和密码登录而不通过重定向。结果是你会得到OK 200和头部,但你也会得到一个错误的响应(响应必须是空的),所以在下一个请求(即getProcesses)你会得到(401)未授权。如果您通过redirect=False
而不是redirect=false
,则猜测结果。一模一样。
2)你必须得到:strLogin="" // the body of the response must be empty strCookie="JSESSIONID=4F67F134840A2C72DBB968D53772FB22; Path=/bonita; HttpOnly"
对于成功getProcesses
你通过你的登录
wc.Headers[HttpRequestHeader.Cookie] = wc.ResponseHeaders[HttpResponseHeader.SetCookie].ToString();
拿到了头前面的例子中,然后调用进程并获得JSON字符串例如格式
"[{\"id\":\"6996906669894804403\",\"icon\":\"\",\"displayDescription\":\"\",\"deploymentDate\":\"2014-11-19 17:57:40.893\",\"description\":\"\",\"activationState\":\"ENABLED\",\"name\":\"Travel request\",\"deployedBy\":\"22\",\"displayName\":\"Travel request\",\"actorinitiatorid\":\"4\",\"last_update_date\":\"2014-11-19 17:57:41.753\",\"configurationState\":\"RESOLVED\",\"version\":\"1.0\"}]"
(或[],这意味着空JSON)
如果cookie未正确传递,您将再次遇到401错误。
解决方案对于.NET 4.5.1
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace BonitaRestApi
{
class BonitaApi
{
private CookieCollection collection;
string strCookietoPass;
string sessionID;
static void Main(string[] args)
{
BonitaApi obj = new BonitaApi();
Task login = new Task(obj.Login);
login.Start();
login.Wait();
Console.ReadLine();
Task GetProcesses = new Task(obj.GetProcesses);
GetProcesses.Start();
GetProcesses.Wait();
Console.ReadLine();
Task logout = new Task(obj.Logout);
logout.Start();
logout.Wait();
Console.ReadLine();
}
public async void Login()
{
const string url = "http://localhost:8080/bonita/";
var cookies = new CookieContainer();
var handler = new HttpClientHandler();
handler.CookieContainer = cookies;
using (var client = new HttpClient(handler))
{
var uri = new Uri(url);
client.BaseAddress = uri;
//client.DefaultRequestHeaders.Accept.Clear();
//client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("username", "helen.kelly"),
new KeyValuePair<string, string>("password", "bpm"),
new KeyValuePair<string, string>("redirect", "false"),
new KeyValuePair<string, string>("redirectUrl", ""),
});
HttpResponseMessage response = await client.PostAsync("loginservice", content);
if (response.IsSuccessStatusCode)
{
var responseBodyAsText = await response.Content.ReadAsStringAsync();
if (!String.IsNullOrEmpty(responseBodyAsText))
{
Console.WriteLine("Unsuccessful Login.Bonita bundle may not have been started, or the URL is invalid.");
return;
}
collection= cookies.GetCookies(uri);
strCookietoPass = response.Headers.GetValues("Set-Cookie").FirstOrDefault();
sessionID = collection["JSESSIONID"].ToString();
Console.WriteLine(string.Format("Successful Login Retrieved session ID {0}", sessionID));
// Do useful work
}
else
{
Console.WriteLine("Login Error" + (int)response.StatusCode + "," + response.ReasonPhrase);
}
}
}
public async void Logout()
{
const string url = "http://localhost:8080/bonita/";
var cookies = new CookieContainer();
var handler = new HttpClientHandler();
handler.CookieContainer = cookies;
using (var client = new HttpClient(handler))
{
var uri = new Uri(url);
client.BaseAddress = uri;
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("redirect", "false")
});
HttpResponseMessage response = await client.PostAsync("logoutservice", content);
if (response.IsSuccessStatusCode)
{
var responseBodyText = await response.Content.ReadAsStringAsync();
if (!String.IsNullOrEmpty(responseBodyText))
{
Console.WriteLine("Unsuccessful Logout.Bonita bundle may not have been started, or the URL is invalid.");
return;
}
Console.WriteLine("Successfully Logged out.");
}
else
{
Console.WriteLine("Logout Error" + (int)response.StatusCode + "," + response.ReasonPhrase);
}
}
}
public async void GetProcesses()
{
var handler = new HttpClientHandler();
Cookie ok = new Cookie("Set-Cookie:",strCookietoPass);
handler.CookieContainer.Add(collection);
using (var client = new HttpClient(handler))
{
var builder = new UriBuilder("http://localhost/bonita/API/bpm/process");
builder.Port = 8080;
var query = HttpUtility.ParseQueryString(builder.Query);
query["p"] = "0";
query["c"] = "10";
builder.Query = query.ToString();
Uri uri= new Uri(builder.ToString());
client.BaseAddress = uri;
HttpResponseMessage response = await client.GetAsync(uri.ToString());
if (response.IsSuccessStatusCode)
{
var responseBodyText = await response.Content.ReadAsStringAsync();
if (String.IsNullOrEmpty(responseBodyText))
{
Console.WriteLine("Unsuccessful GetProcesses.Bonita bundle may not have been started, or the URL is invalid.");
return;
}
Console.WriteLine("Successfully GetProcesses:" + responseBodyText);
}
else
{
Console.WriteLine("GetProcesses Error" + (int)response.StatusCode + "," + response.ReasonPhrase);
}
}
}
}
}
我必须为每一个非GET请求同样的问题(401错误)。
我终于通过这让看的CSRF文档: http://documentation.bonitasoft.com/7.4?page=csrf-security
(见“是否有关于REST API调用的影响?“一节)
succesfull登录后,你必须把一个特殊的头在你的要求:
key: X-Bonita-API-Token
value: the one you got after your login (check the relevant cookie)
奇怪为什么没有在最初的API使用文档页面的任何地方提到这样一个重要的细节感谢这个帮帮我! – buer 2017-02-08 12:20:43