как реализовать вход в Google в ядре .net без провайдера - PullRequest
0 голосов
/ 06 декабря 2018

Я использую логин Google для своего основного сайта .net.

В этом коде

var properties = signInManager.ConfigureExternalAuthenticationProperties("Google", redirectUrl);      
return new ChallengeResult("Google", properties); 

мне нужно signInManager, что (в примере кода) это:

private SignInManager<AppUser> signInManager;

Я внедряю его через конструктор, и затем получаю эту ошибку:

Невозможно разрешить службу для типа 'Microsoft.AspNetCore.Identity.SignInManager1 [AppUser]', покапытаясь активировать AccountController.

Гугл узнал, что я должен включить это

services.AddIdentity<AppUser, IdentityRole>()
    .AddDefaultTokenProviders();`

Но это дает мне эту ошибку:

Невозможноразрешить службу для типа «Microsoft.AspNetCore.Identity.IUserStore1 [AppUser]» при попытке активировать «Microsoft.AspNetCore.Identity.AspNetUserManager1 [AppUser]».

И в этот момент я получаюсовет, чтобы добавить это:

.AddEntityFrameworkStores<ApplicationDbContext>()

Но тогда я потерялся, потому что зачем SignInManager нужно IUserStore, и я должен добавить UserStore и DBContext и EntityFramework магазин, когда я не буду использовать это (для моего входа в Google)?

Так что вопрос: cя также могу войти в Google без магазина Entityframework?

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018

Если все, что вы хотите сделать, - это войти в Google, нет необходимости в SignInManager, UserManager или самой идентификации ядра ASP.NET.Для этого нам сначала необходимо настроить службы аутентификации.Вот соответствующий код для этого, который я объясню после:

Startup.cs

services
    .AddAuthentication(o =>
    {
        o.DefaultScheme = "Application";
        o.DefaultSignInScheme = "External";
    })
    .AddCookie("Application")
    .AddCookie("External")
    .AddGoogle(o =>
    {
        o.ClientId = ...;
        o.ClientSecret = ...;
    });
  • Вызов AddAuthenticationнастраивает DefaultScheme, который в конечном итоге используется как схема Application и схема Challenge .Схема Приложение используется при попытке аутентификации пользователя (они вошли в систему?).Схема Challenge используется, когда пользователь не вошел в систему, но приложение хочет предоставить возможность сделать это.Я расскажу о DefaultSignInScheme позже.

  • Два вызова AddCookie добавляют схемы аутентификации на основе файлов cookie для обеих Application (наша Приложение схема) и External (наша схема SignIn ).AddCookie также может принимать второй аргумент, который позволяет конфигурировать, например, время жизни соответствующего cookie и т. Д.

При этом процесс вызова перенаправит пользователя на /Account/Login (по умолчанию - это также можно настроить с помощью опций аутентификации cookie).Вот реализация контроллера, которая обрабатывает процесс вызова (опять же, я объясню после):

AccountController.cs

public class AccountController : Controller
{
    public IActionResult Login(string returnUrl)
    {
        return new ChallengeResult(
            GoogleDefaults.AuthenticationScheme,
            new AuthenticationProperties
            {
                RedirectUri = Url.Action(nameof(LoginCallback), new { returnUrl })
            });
    }

    public async Task<IActionResult> LoginCallback(string returnUrl)
    {
        var authenticateResult = await HttpContext.AuthenticateAsync("External");

        if (!authenticateResult.Succeeded)
            return BadRequest(); // TODO: Handle this better.

        var claimsIdentity = new ClaimsIdentity("Application");

        claimsIdentity.AddClaim(authenticateResult.Principal.FindFirst(ClaimTypes.NameIdentifier));
        claimsIdentity.AddClaim(authenticateResult.Principal.FindFirst(ClaimTypes.Email));

        await HttpContext.SignInAsync(
            "Application",
            new ClaimsPrincipal(claimsIdentity));

        return LocalRedirect(returnUrl);
    }
}

Давайте разберем это на двадействия:

  1. Login

    Чтобы выполнить действие Login, пользователю будет вызов .Это происходит, когда пользователь не вошел в систему по схеме Application, но пытается получить доступ к странице, защищенной атрибутом Authorize (или аналогичным).По вашему требованию, если пользователь не вошел в систему, мы хотим войти в него с помощью Google.Чтобы добиться этого, мы запускаем новый вызов , на этот раз для схемы Google.Мы делаем это, используя ChallengeResult, настроенный по схеме Google, и RedirectUrl, который используется для возврата к нашему собственному коду приложения после завершения процесса входа в Google.Как показывает код, мы возвращаемся к:

  2. LoginCallback

    Здесь DefaultSignInScheme от нашего звонка до AddAuthentication становится актуальным.Как часть процесса входа в Google, DefaultSignInScheme используется для установки файла cookie, который содержит ClaimsPrincipal, представляющий пользователя, возвращенного из Google (все это обрабатывается за кулисами).Первая строка кода в LoginCallback захватывает этот экземпляр ClaimsPrincipal, который заключен в AuthenticateResult, который сначала проверяется на успешность.Если до сих пор все прошло успешно, мы заканчиваем тем, что создаем новый ClaimsPrincipal, который содержит все требования, которые нам нужны (взятые от Google в данном случае), а затем регистрируем этот ClaimsPrincipal, используя схему Application.Наконец, мы перенаправляем на страницу, которая вызвала наш первый вызов .


Я создал репозиторий GitHub, содержащий полный пример, который я встроилчтобы написать этот ответ здесь .


В ответ на пару последующих комментариев / вопросов в комментариях ниже:

Могу ли ясделать вывод, что SignInManager и UserManager используются только при использовании аутентификации с базой данных?

В некотором смысле, да, я думаю, это справедливо.Хотя возможно реализовать хранилище в памяти, на самом деле это не имеет особого смысла, если нет постоянства.Однако настоящая причина не использовать эти классы в вашей ситуации просто потому, что вам не нужна локальная учетная запись пользователя для представления пользователя.Это идет рука об руку с постоянством, но стоит провести различие.

И какой код сильно отличается от того, что я прочитал в книге (которую я использовал для настройки своего входа в Google) ивсе остальные ответы, которые я прочитал.

Документация и книги охватывают наиболее распространенный вариант использования, при котором вы делаете хотите хранить локальных пользователей, которые могут быть связаны с внешними учетными записями, такими как Google и т. Д. Еслиесли вы посмотрите на источник SignInManager, то увидите, что он действительно находится поверх кода, который я показал выше (например, здесь и здесь ).Другой код можно найти в пользовательском интерфейсе по умолчанию (например, здесь ) и в AddIdentity.

Я предполагаю, что LoginCallback вызывается Google.HttpContext.AuthenticateAsync знает, как проверить данные, которые Google отправляет мне?И поскольку его название настолько общее, похоже, оно знает, как это сделать для всех внешних провайдеров?

Звонок AuthenticateAsync здесь не знает ничего оGoogle - специфичная для Google обработка настраивается путем вызова на AddGoogle с AddAuthentication в ConfigureServices.После перенаправления в Google для входа мы на самом деле возвращаемся к /signin-google в нашем приложении.Опять же, это обрабатывается благодаря вызову AddGoogle, но этот код на самом деле просто генерирует cookie в схеме External, в которой хранятся утверждения, полученные от Google, и затем перенаправляется на нашу конечную точку LoginCallback, которую мы настроили,Если вы добавите вызов к AddFacebook, конечная точка /sigin-facebook будет настроена на аналогичные действия.Вызов AuthenticateAsync на самом деле просто повторяет запрос ClaimsPrincipal из файла cookie, который был создан, например, конечной точкой /signin-google, чтобы получить претензии.

Стоит также отметить, что Google / FacebookПроцесс входа в систему основан на протоколе OAuth 2 , поэтому он сам по себе является общим.Если вам нужна поддержка не только для Google, вы просто вызовете задачу для требуемой схемы, а не жестко закодируете ее для Google, как я делал в примере.Также можно добавить дополнительные свойства к запросу, чтобы иметь возможность определить, какой поставщик использовался при достижении вашей конечной точки LoginCallback.

0 голосов
/ 08 декабря 2018

Если вы не хотите использовать Entity Framework, тогда вам нужно выбрать провайдера хранилища: https://docs.microsoft.com/en-us/aspnet/identity/overview/extensibility/overview-of-custom-storage-providers-for-aspnet-identity Если вы хотите использовать Entity Framework, но у вас возникла ошибка (как вы описали), вы можете сослаться на мой источникдемо:

https://bitbucket.org/tuanv2t/net-core-demo/src/master/NetCoreDemo/GoogleLoginDemo/

...