[英]Authentication from C# HttpClient against Spring server JWT Tokens
我正在編寫Xamarin跨平台移動應用程序。 該服務器是一台SpringMVC服務器,它使用JWT令牌針對每個端點/ Web服務進行身份驗證。 因此,基本上,當我第一次向Web服務發出請求時,在需要點擊/authorize
POST端點發送我的電子郵件和密碼之前,端點響應將在"Cookie"
標頭中包含一個身份驗證令牌,該令牌為"AUTH_TOKEN={MD5-String}"
。 一旦獲得令牌,就將請求發送到端點,比如說/feed
。 但是我的問題是我無法弄清楚在C# HttpClient
中設置“ Cookie”標頭的方式。 我嘗試了所有方法,但是endpoing只是繼續使用登錄屏幕html而不是實際的JSON響應進行響應。 我在Postman和其他REST客戶端中嘗試了相同的步驟,並且有效。 所以這意味着我做錯了。 這是我的代碼:
public class RestService : IRestService
{
HttpClient client;
HttpClientHandler handler;
CookieContainer cookies;
string authToken;
public List<Feed> FeedItems { get; private set; }
public RestService()
{
cookies = new CookieContainer();
handler = new HttpClientHandler();
handler.UseCookies = true; //Otherwise It'll not use the cookies container!!
handler.CookieContainer = cookies;
client = new HttpClient(handler);
client.MaxResponseContentBufferSize = 256000;
}
public async Task<List<Role>> GetFeedDataAsync()
{
//Request credentials
//Credentials validation
var credentials = new HalliganCredential()
{
email = Constants.Username,
password = Constants.Password
};
var jsonCredentials = JsonConvert.SerializeObject(credentials);
var jsonCredentialsContent = new StringContent(jsonCredentials, Encoding.UTF8, "application/json");
var authorizeUri = new Uri(Constants.AuthorizeEndpoint);
var authorizeResponse = await client.PostAsync(authorizeUri, jsonCredentialsContent);
if (authorizeResponse.IsSuccessStatusCode)
{
//If authentication went OK
IEnumerable<Cookie> responseCookies = cookies.GetCookies(authorizeUri).Cast<Cookie>();
foreach (Cookie cookie in responseCookies)
{
if (cookie.Name.Equals("AUTH-TOKEN"))
{
authToken = cookie.Value;
}
}
}
else
{
//Authentication failed throw error
throw new HttpRequestException("Authentication failed");
}
FeedItems = new List<Feed>();
//Making the GET request
var uri = new Uri(string.Format(Constants.FeedEnpoint, string.Empty));
try
{
cookies.Add(uri, new Cookie("Cookie", string.Format("AUTH_TOKEN={0}", authToken)));
client.DefaultRequestHeaders.Add("Cookie", string.Format("AUTH_TOKEN={0}", authToken));
handler.CookieContainer.Add(uri, new Cookie("Cookie", string.Format("AUTH_TOKEN={0}", authToken)));
var response = await client.GetAsync(uri);
response.EnsureSuccessStatusCode();
//Credentials validation
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
FeedItems = JsonConvert.DeserializeObject<List<Feed>>(content);
}
}
catch (Exception ex)
{
Debug.WriteLine(@"ERROR {0}", ex.Message);
}
return FeedItems;
}
}
當我到達那行時, var content = await response.Content.ReadAsStringAsync();
響應是一個HTML字符串,而不是實際的JSON響應。
盡管"Cookie"
是用於Postman的那個,但我嘗試使用其他幾個頭的鍵值。
我嘗試使用"Set-Cookie"
, "set-cookie"
, "Set-Cookie"
,將標題設置為"AUTH_TOKEN"
。 我在不同的地方嘗試了所有這些說服力,例如將它們添加到cookie
CookieContainer
, handler
CookieContainer
和client.DefaultRequestHeaders
。
我嘗試打開和關閉處理程序handler.UseCookies = true; //Otherwise It'll not use the cookies container!!
handler.UseCookies = true; //Otherwise It'll not use the cookies container!!
線。
任何幫助都將受到歡迎!
更新
我嘗試了一種建議的解決方案,但沒有用,無論是對還是錯,我都對UseCookies進行了嘗試。
//Making the GET request
var baseAddress = new Uri("http://app.******.io");
using (var handler = new HttpClientHandler { UseCookies = true })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
var message = new HttpRequestMessage(HttpMethod.Get, "/api/v1/feed?api_key=sarasa");
message.Headers.Add("Cookie", string.Format("AUTH_TOKEN={0}", authToken));
message.Headers.Add("Cookie", string.Format("AUTH_TOKEN={0};", authToken));
message.Headers.Add("Set-Cookie", string.Format("AUTH_TOKEN={0}", authToken));
message.Headers.Add("AUTH_TOKEN", authToken);
var result = await client.SendAsync(message);
result.EnsureSuccessStatusCode();
if (result.IsSuccessStatusCode)
{
var content = await result.Content.ReadAsStringAsync();
FeedItems= JsonConvert.DeserializeObject<List<Feed>>(content);
}
}
return FeedItems;
更新
我嘗試了另一種解決方案,結果相同。
var baseAddress = new Uri("http://app.*****.io");
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
cookieContainer.Add(baseAddress, new Cookie("Cookie", string.Format("AUTH_TOKEN={0}", authToken)));
cookieContainer.Add(baseAddress, new Cookie("Set-Cookie", string.Format("AUTH_TOKEN={0}", authToken)));
var result = client.GetAsync("/api/v1/roles?api_key=sarasa").Result;
result.EnsureSuccessStatusCode();
if (result.IsSuccessStatusCode)
{
var content = await result.Content.ReadAsStringAsync();
RolesItems = JsonConvert.DeserializeObject<List<Role>>(content);
}
}
HttpClient
是否有替代方法?
我終於可以設置Cookie標頭參數,但是我通過HttpWebRequest
更改HttpClient
獲取餅干
//Credentials validation
var credentials = new CompanyCredential()
{
Email = Constants.Username,
Password = Constants.Password
};
var jsonCredentials = JsonConvert.SerializeObject(credentials);
var request = (HttpWebRequest) WebRequest.Create(new Uri(baseAddress, Constants.AuthorizeEndpoint));
request.ContentType = "application/json";
request.Method = "POST";
var requestStream = request.GetRequestStreamAsync().Result;
var streamWriter = new StreamWriter(requestStream);
streamWriter.Write(jsonCredentials);
streamWriter.Flush();
try
{
HttpWebResponse response = (HttpWebResponse) request.GetResponseAsync().Result;
if (response.StatusCode.Equals(HttpStatusCode.OK))
{
authToken = response.Headers["Set-Cookie"];
tokenExpireDate = DateTime.ParseExact(response.Headers["Expires"], "yyyy-MM-dd HH:mm:ss,fff",
System.Globalization.CultureInfo.InvariantCulture);
}
else
{
//Authentication failed throw error
throw new HttpRequestException("Authentication failed");
}
} catch (Exception e)
{
Debug.WriteLine(string.Format("Warning: {0}", e.Message));
}
設置餅干
var request = (HttpWebRequest)WebRequest.Create(new Uri(baseAddress, endpoint));
SetHeaders(request);
if (string.IsNullOrEmpty(authToken))
{
throw new AuthTokenNullException();
}
request.Headers["Cookie"] = authToken;
request.Method = "GET";
HttpWebResponse response = request.GetResponseAsync().Result as HttpWebResponse;
if (!response.StatusCode.Equals(HttpStatusCode.OK))
{
throw new HttpRequestException(string.Format("Warning expected response as 200 and got {0}", Convert.ToString(response.StatusCode)));
}
var reader = new StreamReader(response.GetResponseStream());
string stringResponse = reader.ReadToEnd();
return JsonConvert.DeserializeObject<T>(stringResponse);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.