在Xamarin上使用AntiForgeryToken访问Aspnet 5.0中的WebAPI
在Xamarin上使用AntiForgeryToken访问Aspnet 5.0中的WebAPI
我正在尝试访问一个使用ValidateAntiForgeryToken的WebAPI。我的WebAPI方法如下(一个简单的方法),它位于一个用户控制器中(仅用于测试):\n
[HttpPost] [ValidateAntiForgeryToken] public ActionResult Test(String field) { String result = String.Empty; if (ModelState.IsValid) { HtmlSanitizer sanitizer = new HtmlSanitizer(); try { result = sanitizer.Sanitize(field); } catch (Exception ex) { result = ex.Message; throw; } } return Json(result); }
\n通过Ajax,我可以轻松访问它:\n
$.ajax({ url: '/User/Test', type: "POST", contentType: "application/x-www-form-urlencoded", data: { field: self.textField(), __RequestVerificationToken: $("input[name='__RequestVerificationToken']").val(), }, success: function(e) { self.textField(e) self.divField(e); }, error: function(e) { console.log(e.error()); }, });
\n但是,到目前为止,我无法使用Xamarin中的HttpClient访问此WebAPI。这是我的代码:\n
private async void DoTestWebApi() { try { HttpClient clientPage = new HttpClient() { BaseAddress = new Uri("https://localhost:44356/user") }; var pageWithToken = await clientPage.GetAsync(clientPage.BaseAddress); String verificationToken = GetVerificationToken(await pageWithToken.Content.ReadAsStringAsync()); HttpClient client = new HttpClient() { BaseAddress = new Uri("https://localhost:44356/user/test/") }; HttpRequestMessage message = new HttpRequestMessage() { RequestUri = new Uri("https://localhost:44356/user/test/"), Method = HttpMethod.Post }; message.Headers.Add("__RequestVerificationToken", verificationToken); String field = "teste"; StringContent content = new StringContent("__RequestVerificationToken=" + verificationToken + ",field=test", Encoding.UTF8, "application/x-www-form-urlencoded"); var response2 = await client.SendAsync(message); if (response2.IsSuccessStatusCode) { var t = response2.Content.ReadAsStringAsync(); if (true) { // just to check if t has value } } } catch (Exception ex) { Console.WriteLine(ex.Message); throw; } }
\n老实说,我不知道还能做什么来在消息中传递我的防伪标记。它在ajax中完美运行,我将其传递给数据内容,但在Xamarin中不起作用。\n所有的代码都在同一台本地主机上执行。如果我删除[ValidateAntiForgeryToken],它可以工作。\n我错过了什么吗?\n编辑:\n好吧,现在我正在使用cookie发送,但它没有再次命中方法。\n这是我的更新:\n
HttpClient clientPage = new HttpClient() { BaseAddress = new Uri("https://localhost:44356/user") }; var pageWithToken = await clientPage.GetAsync(clientPage.BaseAddress); String verificationToken = GetVerificationToken(await pageWithToken.Content.ReadAsStringAsync()); List> cookiesInfo = new List >(); foreach (var item in pageWithToken.Headers) { cookiesInfo.Add(new KeyValuePair (item.Key, item.Value.ToString())); } cookiesInfo.Add(new KeyValuePair ("field", "value")); cookiesInfo.Add(new KeyValuePair ("__RequestVerificationToken", verificationToken)); CookieContainer cookieContainer = new CookieContainer(); using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer }) { using (var client = new HttpClient(handler) { BaseAddress = new Uri("https://localhost:44356/user") }) { var content = new FormUrlEncodedContent(cookiesInfo); cookieContainer.Add(client.BaseAddress, new Cookie("__RequestVerificationToken", verificationToken)); foreach (var item in cookiesInfo) { cookieContainer.Add(client.BaseAddress, new Cookie(item.Key, item.Value)); } var result = client.PostAsync(new Uri("https://localhost:44356/user/test"), content).Result; result.EnsureSuccessStatusCode(); } };
\n这让我抓狂...好吧,测试是在本地主机上,但很快这个应用程序将在Azure上运行,这是一个先决条件...\n编辑:GetVerificationToken方法:\n
private string GetVerificationToken(String verificationToken) { if (verificationToken != null && verificationToken.Length > 0) { verificationToken = verificationToken.Substring(verificationToken.IndexOf("__RequestVerificationToken")); verificationToken = verificationToken.Substring(verificationToken.IndexOf("value=\"") + 7); verificationToken = verificationToken.Substring(0, verificationToken.IndexOf("\"")); } return verificationToken; }
问题:在使用Aspnet 5.0和Xamarin开发中,访问带有AntiForgeryToken的WebAPI时,出现了什么问题?
问题的原因:在发送数据到使用AntiForgeryToken的WebAPI时,缺少了cookie。
解决方法:在访问WebAPI之前,需要获取页面上的AntiForgeryToken,并将其添加到请求中的内容中。同时,需要确保在发送请求时携带了cookie。
具体解决方法如下:
private async void DoTestWebApi() { try { CookieContainer cookieContainer = new CookieContainer(); HttpClientHandler handlerhttps = new HttpClientHandler { UseCookies = true, UseDefaultCredentials = true, CookieContainer = cookieContainer }; HttpClient clientPage = new HttpClient(handlerhttps) { BaseAddress = new Uri("https://localhost:44356/user") }; var pageWithToken = await clientPage.GetAsync(clientPage.BaseAddress); String verificationToken = GetVerificationToken(await pageWithToken.Content.ReadAsStringAsync()); var cookies = cookieContainer.GetCookies(new Uri("https://localhost:44356/user")); using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer, UseDefaultCredentials = true, UseCookies = true }) { using (var client = new HttpClient(handler) { BaseAddress = new Uri("https://localhost:44356/user/test") }) { var contentToSend = new FormUrlEncodedContent(new[] { new KeyValuePair("field", "value"), new KeyValuePair ("__RequestVerificationToken", verificationToken), }); var response = client.PostAsync(client.BaseAddress, contentToSend).Result; } }; } catch (Exception ex) { Console.WriteLine(ex.Message); } }
通过以上代码,可以解决在访问带有AntiForgeryToken的WebAPI时缺少cookie的问题。