Skip to main content
 首页 » 编程设计

c#之在 Xamarin 上的 Asp Net 5.0 中使用 AntiForgeryToken 访问 Web API

2024年02月27日39飞鱼

我正在尝试访问使用 ValidateAntiForgeryToken 的 WebAPI。我的 WebAPI 方法是这个(一个简单的方法),它在用户 Controller 中(仅用于测试):

[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); 
} 

使用 Ajax,我可以轻松访问它:

$.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()); 
    }, 
}); 

但是,直到现在,我都无法在 xamarin 上使用 httpclient 访问这个 webapi。这是我的代码:

    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("field=test", Encoding.UTF8, "application/x-www-form-urlencoded"); 
        StringContent content = new StringContent("__RequestVerificationToken=" + verificationToken + ",field=test", Encoding.UTF8, "application/x-www-form-urlencoded"); 
 
        // this doesn't work 
        //client.DefaultRequestHeaders.Add("__RequestVerificationToken", verificationToken); 
        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; 
    } 
 
} 

老实说,我不知道我还能做些什么来在消息中传递我的防伪标记。它在 ajax 中完美运行,我在数据内容中传递它,但在 xamarin 中它不起作用。 所有代码都在同一本地主机内执行。如果我删除 [ValidateAntiForgeryToken],它会起作用。

我错过了什么?

编辑:

好的,现在我用 cookie 发送,但不再点击该方法。 这是我的更新:

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<KeyValuePair<String, String>> cookiesInfo = new List<KeyValuePair<String, String>>(); 
 
foreach (var item in pageWithToken.Headers) 
{ 
    cookiesInfo.Add(new KeyValuePair<String, String>(item.Key, item.Value.ToString())); 
} 
 
cookiesInfo.Add(new KeyValuePair<string, string>("field", "value")); 
cookiesInfo.Add(new KeyValuePair<string, string>("__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(); 
    } 
 
}; 

这让我抓狂……好吧,测试是在本地主机上进行的,但很快这个应用程序将在 Azure 中,这是先决条件……


编辑:GetVerificationToken 方法:

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; 
    } 

请您参考如下方法:

ValidateAntiForgeryToken 还需要一个带有 __RequestVerificationToken 和所提供值的 cookie。这是为了确保向 Controller 发帖的人是查看表单的人。