Вход в приложение ASP.NET Core не работает на реальном устройстве Android с .NET HttpClient в приложении Xamarin.Forms - PullRequest
0 голосов
/ 20 сентября 2019

Получил приложение Xamarin.Forms, которое запрашивает данные через API, реализованный в ASP.NET Core.Перед получением данных приложение должно войти в приложение ASP.Net Core, которое использует службу идентификации.Код прекрасно работает в iOS Simulator, Android 9 Emulator и на реальном iPhone, но не на реальном устройстве Android 9!Сетевое соединение работает хорошо, потому что я могу получить доступ к веб-приложению через браузер.

Я использую System.Net.Http.HttpClient в общем проекте.Служба идентификации требует отправки ключа защиты от подделки (Кстати: есть ли лучший способ обработки авторизации только для веб-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

Мне интересно, почемусначала в журнале написано "Пользователь вошели позже "Авторизация не удалась."Может ли быть проблема с печеньем?Скажу просто, я работаю в тестовой среде без шифрования -> только http.

Спасибо за помощь!

1 Ответ

0 голосов
/ 24 сентября 2019

Наконец-то нашли решение!Я предположил, что с куки-файлами Identities что-то не так, поскольку вход выполнен успешно, но дальнейшие запросы об этом забывают.Identity сохраняет cookie на стороне клиента для аутентификации после успешного входа в систему и отправляет его на сервер при каждом запросе.Для доступа к файлам cookie HttpClient во время инициализации требуется дополнительный код:

HttpClientHandler _httpClientHandler = new HttpClientHandler();

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

Добавление HttpClienthandler в HttpClient помогло!Я не уверен, почему это нужно для Android, но не для iOS.Может быть, у кого-то есть предположение?

...