使用 Xamarin.Forms 应用程序中的 .NET HttpClient 登录到 ASP.NET Core 应用程序在 Android 真实设备上不起作用

精神分裂症

有一个 Xamarin.Forms 应用程序,它通过在 ASP.NET Core 中实现的 API 请求数据。在检索数据之前,应用程序必须登录到使用身份服务的 ASP.Net Core 应用程序。该代码在 iOS 模拟器、Android 9 模拟器和真正的 iPhone 上运行良好,但不适用于真正的 Android 9 设备!网络连接运行良好,因为我可以通过浏览器访问 Web 应用程序。

我在共享项目中使用 System.Net.Http.HttpClient。身份服务需要发送防伪密钥(顺便说一句:有没有更好的方法来处理仅针对 web api 的授权?处理防伪密钥似乎不方便)。这是处理登录过程的代码:

    private async Task LoginAsync(string username, string password)
    {
        //Get login page with AntiForgeryToken
        var pageWithToken = await _httpClient.GetStringAsync(BASE_URL);

        //Extract AntiForgeryToken
        string verificationToken = GetAntiForgeryToken(pageWithToken);

        //Post parameter
        var keyValues = new List<KeyValuePair<string, string>>
                {
                    new KeyValuePair<string, string>("Input.Email", username),
                    new KeyValuePair<string, string>("Input.Password", password),
                    new KeyValuePair<string, string>("__RequestVerificationToken", verificationToken),
                    new KeyValuePair<string, string>("Input.RememberMe", "false")
                };

        var request = new HttpRequestMessage(HttpMethod.Post, "Identity/Account/Login")
        {
            Content = new FormUrlEncodedContent(keyValues)
        };

        //login with Post parameter
        var response = await _httpClient.SendAsync(request);

        //read response - can see here that login failed
        var content = await response.Content.ReadAsStringAsync();
    }

这是我在发送带有登录数据的 Post 请求后在服务器端看到的:

Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST http://10.219.200.147:33224/Identity/Account/Login application/x-www-form-urlencoded 253
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executing endpoint 'Page: /Account/Login'
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Route matched with {page = "/Account/Login", area = "Identity", action = "", controller = ""}. Executing page /Account/Login
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executing handler method C4S.WebApp.Areas.Identity.Pages.Account.LoginModel.OnPostAsync with arguments () - ModelState is Valid
Microsoft.EntityFrameworkCore.Infrastructure:Information: Entity Framework Core 2.2.6-servicing-10079 initialized 'ApplicationDbContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: None
Der Thread 0x28d4 hat mit Code 0 (0x0) geendet.
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (9ms) [Parameters=[@__normalizedUserName_0='?' (Size = 256)], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [u].[Id], [u].[AccessFailedCount], [u].[ConcurrencyStamp], [u].[Email], [u].[EmailConfirmed], [u].[LockoutEnabled], [u].[LockoutEnd], [u].[NormalizedEmail], [u].[NormalizedUserName], [u].[PasswordHash], [u].[PhoneNumber], [u].[PhoneNumberConfirmed], [u].[SecurityStamp], [u].[TwoFactorEnabled], [u].[UserName]
FROM [AspNetUsers] AS [u]
WHERE [u].[NormalizedUserName] = @__normalizedUserName_0
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (2ms) [Parameters=[@__user_Id_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30']
SELECT [uc].[Id], [uc].[ClaimType], [uc].[ClaimValue], [uc].[UserId]
FROM [AspNetUserClaims] AS [uc]
WHERE [uc].[UserId] = @__user_Id_0
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Identity.Application signed in.
C4S.WebApp.Areas.Identity.Pages.Account.LoginModel:Information: User logged in.
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executed handler method OnPostAsync, returned result Microsoft.AspNetCore.Mvc.LocalRedirectResult.
Microsoft.AspNetCore.Mvc.Infrastructure.LocalRedirectResultExecutor:Information: Executing LocalRedirectResult, redirecting to /.
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executed page /Account/Login in 112.8493ms
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executed endpoint 'Page: /Account/Login'
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 131.0183ms 302 
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://10.219.200.147:33224/  
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executing endpoint 'Page: /Kontakte/Index'
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Route matched with {page = "/Kontakte/Index", action = "", controller = "", area = ""}. Executing page /Kontakte/Index
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed.
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Identity.Application was challenged.
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executed page /Kontakte/Index in 6.2539ms
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executed endpoint 'Page: /Kontakte/Index'
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 14.9729ms 302 
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://10.219.200.147:33224/Identity/Account/Login?ReturnUrl=%2F  
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executing endpoint 'Page: /Account/Login'
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Route matched with {page = "/Account/Login", area = "Identity", action = "", controller = ""}. Executing page /Account/Login
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executing handler method C4S.WebApp.Areas.Identity.Pages.Account.LoginModel.OnGetAsync with arguments (/) - ModelState is Valid
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Identity.External signed out.
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executed handler method OnGetAsync, returned result .
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executing an implicit handler method - ModelState is Valid
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executed page /Account/Login in 11.6849ms
Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executed endpoint 'Page: /Account/Login'
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 20.9535ms 200 text/html; charset=utf-8

我想知道为什么日志首先显示“用户已登录”。后来“授权失败。”。可能有cookie问题吗?只是说,我在没有加密的测试环境中工作-> 只有 http。

谢谢你的帮助!

精神分裂症

终于找到解决办法了!我认为身份 cookie 有问题,因为登录成功但进一步的请求似乎忘记了这一点。Identity 在客户端存储一个 cookie 用于成功登录后的身份验证,并在每次请求时将其发送到服务器。在初始化时访问 HttpClient 的 cookie 需要一些额外的代码:

HttpClientHandler _httpClientHandler = new HttpClientHandler();

HttpClient _httpClient = new HttpClient(_httpClientHandler) { BaseAddress = new Uri(BASE_URL), Timeout = new TimeSpan(0, 0, 30) };

将 HttpClienthandler 添加到 HttpClient 就成功了!我不确定为什么 Android 需要它,而 iOS 不需要。也许有人有一个猜测?

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

Related 相关文章

热门标签

归档