.NET Core Identity Server 4 Аутентифікація VS Identity Authentication


94

Я намагаюся зрозуміти правильний спосіб автентифікації в ASP.NET Core. Я переглянув кілька ресурсів (більшість із яких застарілі).

Деякі люди пропонують альтернативні рішення, в яких заявляється про використання хмарного рішення, такого як Azure AD, або про використання IdentityServer4 та розміщення мого власного Token Server.

У старшій версії .Net однією з простіших форм автентифікації було б створити власний Iprinciple та зберігати всередині додаткові дані щодо автентифікації.

public interface ICustomPrincipal : System.Security.Principal.IPrincipal
{
    string FirstName { get; set; }

    string LastName { get; set; }
}

public class CustomPrincipal : ICustomPrincipal
{
    public IIdentity Identity { get; private set; }

    public CustomPrincipal(string username)
    {
        this.Identity = new GenericIdentity(username);
    }

    public bool IsInRole(string role)
    {
        return Identity != null && Identity.IsAuthenticated && 
           !string.IsNullOrWhiteSpace(role) && Roles.IsUserInRole(Identity.Name, role);
    }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string FullName { get { return FirstName + " " + LastName; } }
}

public class CustomPrincipalSerializedModel
{
    public int Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }
}

Потім ви серіалізуєте свої дані у файлі cookie та повертаєте їх назад клієнту.

public void CreateAuthenticationTicket(string username) {     

    var authUser = Repository.Find(u => u.Username == username);  
    CustomPrincipalSerializedModel serializeModel = new CustomPrincipalSerializedModel();

    serializeModel.FirstName = authUser.FirstName;
    serializeModel.LastName = authUser.LastName;
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    string userData = serializer.Serialize(serializeModel);

    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
    1,username,DateTime.Now,DateTime.Now.AddHours(8),false,userData);
    string encTicket = FormsAuthentication.Encrypt(authTicket);
    HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
    Response.Cookies.Add(faCookie);
}

Мої запитання:

  1. Як я можу пройти автентифікацію, подібно до того, як це було зроблено в попередніх версіях .Net, чи все ще працює старий спосіб, чи є нова версія?

  2. Які плюси та мінуси використання власних віршів із сервером лексем, створюючи власний власний принцип?

  3. Використовуючи хмарне рішення або окремий сервер Token, як би ви інтегрували це з вашим поточним додатком, чи все одно мені знадобиться таблиця користувачів у моєму додатку, як би ви пов’язали ці два?

  4. Оскільки існує так багато різних рішень, як я можу створити корпоративний додаток, щоб дозволити вхід через Gmail / Facebook, маючи при цьому можливість розширення до інших єдиних систем

  5. Які прості реалізації цих технологій?

Це питання занадто широке, а також дуже засноване на думках. Існує або занадто багато можливих відповідей, або хороші відповіді були б занадто довгими для цього формату. Будь ласка, додайте деталі, щоб звузити набір відповідей або виділити проблему, на яку можна відповісти у кількох абзацах. Багато хороших запитань формують певний ступінь думок на основі досвіду експертів, але відповіді на це питання, як правило, майже повністю базуються на думках, а не фактах, посиланнях чи конкретних знаннях.
Nkosi

@Nkosi вибачте, фраза була такою. Я уточнив це, щоб бути більш конкретним
Джонні, 5

Відповіді:


146

TL; DR

IdentityServer = послуги шифрування та перевірки маркерів через OAuth 2.0 / OpenId-Connect

ASP.NET Identity = поточна стратегія управління ідентифікацією в ASP.NET

Як я можу пройти автентифікацію, подібно до того, як це було зроблено в попередніх версіях .Net, чи все ще працює старий спосіб, чи є нова версія?

Я не бачу жодної причини, чому ви не змогли досягти колишнього шляху в ASP.NET Core, але загалом ця стратегія була замінена на ASP.NET Identity, і ASP.NET Identity живий і здоровий в ASP.NET Core.

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity

ASP.NET Identity використовує резервне сховище, таке як SQL Server, для зберігання інформації про користувача, як-от ім'я користувача, пароль (хешований), електронну пошту, телефон, і легко розширюється для зберігання Імені, Прізвища чи будь-якого іншого. Отже, насправді немає причин шифрувати інформацію про користувача у файлі cookie та передавати її туди-сюди від клієнта до сервера. Він підтримує такі поняття, як заявки користувачів, маркери користувачів, ролі користувачів та зовнішні логіни. Ось сутності в ідентичності ASP.NET:

  • AspNetUsers
  • AspNetUserRoles
  • AspNetUserClaims
  • AspNetUserLogins (для зв’язування зовнішніх постачальників ідентифікаційних послуг, таких як Google, AAD)
  • AspNetUserTokens (для зберігання таких речей, як access_tokens та refresh_tokens, накопичені користувачем)

Які плюси та мінуси використання власних віршів із сервером лексем, створюючи власний власний принцип?

Сервер маркерів буде системою, яка генерує просту структуру даних, що містить інформацію про авторизацію та / або аутентифікацію. Авторизація, як правило, приймає для маркера з іменем access_token . Так би мовити, це "ключі від будинку", що пропускають вас через дверний проріз і перебувають у резиденції захищеного ресурсу, як правило, веб-API. Для автентифікації id_tokenмістить унікальний ідентифікатор користувача / особи. Хоча такий ідентифікатор прийнято вносити в access_token, зараз для цього існує спеціальний протокол: OpenID-Connect .

Причиною власної служби безпеки токенів (STS) є захист ваших інформаційних активів за допомогою криптографії та контроль того, які клієнти (програми) можуть отримати доступ до цих ресурсів. Крім того, стандарти специфіки контролю ідентичності тепер існують у специфікаціях OpenID-Connect. IdentityServer - це приклад сервера авторизації OAuth 2.0 у поєднанні з сервером автентифікації OpenID-Connect.

Але нічого з цього не потрібно, якщо вам просто потрібна таблиця користувачів у вашому додатку. Вам не потрібен маркерний сервер - просто використовуйте ідентифікатор ASP.NET. ASP.NET Identity відображає вашого користувача до ClaimsIdentity об'єкта на сервері - немає потреби у власному класі IPrincipal.

Використовуючи хмарне рішення або окремий сервер Token, як би ви інтегрували це з вашим поточним додатком, чи все одно мені знадобиться таблиця користувачів у моєму додатку, як би ви пов’язали ці два?

Перегляньте ці посібники з інтеграції окремих рішень для ідентифікації з додатком: https://identityserver4.readthedocs.io/en/latest/quickstarts/0_overview.html https://auth0.com/docs/quickstart/webapp/aspnet-core

Як мінімум вам знадобиться таблиця у два стовпці, що відображає ім’я користувача до ідентифікатора користувача зовнішнього постачальника. Це те, що робить таблиця AspNetUserLogins в ідентифікації ASP.NET. Рядки в цій таблиці, однак, залежать від того, що є записом користувача в AspNetUsers.

ASP.NET Identity підтримує зовнішніх постачальників, таких як Google, Microsoft, Facebook, будь-який постачальник OpenID-Connect, Azure AD вже є. (Google і Microsoft вже впровадили протокол OpenID-Connect, тому вам також не потрібні їх власні пакети інтеграції, як , наприклад, цей ). Крім того, ADFS ще не доступний в ASP.NET Core Identity.

Перегляньте цей документ, щоб розпочати роботу із зовнішніми постачальниками в ідентифікації ASP.NET:

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/

Оскільки існує так багато різних рішень, як я можу створити корпоративний додаток, щоб дозволити вхід через Gmail / Facebook, маючи при цьому можливість розширення до інших єдиних систем

Як пояснювалося вище, ASP.NET Identity це вже робить. Створити таблицю "Зовнішні постачальники" досить просто, а дані керують процесом зовнішнього входу. Тож, коли з’являється новий "SSO", просто додайте новий рядок із такими властивостями, як URL-адреса постачальника, ідентифікатор клієнта та секрет, який вони вам дають. ASP.NET Identity вже має вбудований інтерфейс, вбудований там шаблони Visual Studio, але див. Social Login для кнопок охолодження.

Резюме

Якщо вам просто потрібна таблиця користувачів із можливостями входу за паролем та профілем користувача, тоді ідентифікація ASP.NET ідеальна. Не потрібно залучати зовнішні органи. Але, якщо у вас багато додатків, які потребують доступу до багатьох API, тоді незалежний орган із захисту та перевірки ідентичності та маркерів доступу має сенс. IdentityServer добре підходить, або див. Openiddict-core або Auth0 для хмарного рішення.

Приношу свої вибачення, що це не є ціллю або якщо це занадто вступно. Будь ласка, не соромтеся взаємодіяти, щоб дійти до бичачого ока, якого ви шукаєте.

Додаток: Аутентифікація файлів cookie

Щоб виконати автентифікацію оголених кісток за допомогою файлів cookie, виконайте такі дії. Але, наскільки мені відомо, призначений для користувача претензійний принцип не підтримується. Щоб досягти того самого ефекту, скористайтеся списком претензій ClaimPrincipalоб'єкта.

Створіть нову веб-програму ASP.NET Core 1.1 у Visual Studio 2015/2017, вибравши "Без автентифікації" у діалоговому вікні. Потім додайте пакет:

Microsoft.AspNetCore.Authentication.Cookies

За наявним Configureметодом Startup.csце (раніше app.UseMvc):

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationScheme = "MyCookieMiddlewareInstance",
    LoginPath = new PathString("/Controller/Login/"),
    AutomaticAuthenticate = true,
    AutomaticChallenge = true
});

Потім побудуйте інтерфейс користувача для входу та опублікуйте html-форму до методу дії, наприклад:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(String username, String password, String returnUrl = null)
{
    ViewData["ReturnUrl"] = returnUrl;
    if (ModelState.IsValid)
    {
        // check user's password hash in database
        // retrieve user info

        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name, username),
            new Claim("FirstName", "Alice"),
            new Claim("LastName", "Smith")
        };

        var identity = new ClaimsIdentity(claims, "Password");

        var principal = new ClaimsPrincipal(identity);

        await HttpContext.Authentication.SignInAsync("MyCookieMiddlewareInstance", principal);

        return RedirectToLocal(returnUrl);
    }

    ModelState.AddModelError(String.Empty, "Invalid login attempt.");

    return View();
}

Об'єкт HttpContext.User повинен мати ваші власні вимоги та легко отримувати колекцію List з ClaimPrincipal.

Я сподіваюся, цього вистачить, оскільки повне рішення / проект здається трохи великим для публікації StackOverflow.


1
Будь ласка, покажіть приклад реалізації автентифікації в ядрі
Джонні 5

2
Документи ASP.NET Core показують канонічний приклад: docs.microsoft.com/en-us/aspnet/core/security/authentication/… .
travis.js

Якщо ви можете розмістити простий приклад автентифікації. Без посилання, щоб люди мали доступ до ресурсу, я розміщу глибоку відповідь про те, як налаштувати IdentityServer4
Джонні, 5

Для IdentityServer, чи є тут приклад, який ви шукаєте: identserver4.readthedocs.io/en/dev/quickstarts/… ?
travis.js 01.03.17

Для ідентичності ASP.NET, чи не є це приклад, чи це те, що ви говорите, застаріле? docs.microsoft.com/en-us/aspnet/core/security/authentication/…
travis.js

11

TL; DR

Я б дуже хотів показати повну публікацію про те, як правильно реалізувати IdentityServer4, але я намагався вмістити весь текст, але це виходило за межі того, що приймає StackOverflow, тому замість цього я виправлю деякі поради та речі, які я дізнався.

Які переваги використання Token Server Vs ASP Identity?

Токен-сервер має багато переваг, але не для всіх. Якщо ви впроваджуєте рішення, подібне до корпоративного, де ви хочете, щоб кілька клієнтів могли ввійти в систему, найкращим вибором буде сервер Token, але якщо ви просто робите простий веб-сайт, який хоче підтримувати зовнішні входи, ви можете позбутися ідентифікації ASP та деяке проміжне програмне забезпечення.

Identity Server 4 Поради

Ідентифікаційний сервер 4 досить добре задокументований у порівнянні з багатьма іншими фреймворками, які я бачив, але важко починати з нуля і бачити всю картину.

Моя перша помилка намагалася використовувати OAuth як аутентифікацію. Так, є способи зробити це, але OAuth призначений для авторизації, а не автентифікації, якщо ви хочете автентифікувати використання OpenIdConnect (OIDC)

У моєму випадку я хотів створити клієнт javascript, який підключається до веб-API. Я розглядав багато рішень, але спочатку я намагався використовувати webapi для виклику автентифікації проти Identity Server і просто мав зберегти цей маркер, оскільки він був перевірений на сервері. Цей потік потенційно може працювати, але він має багато недоліків.

Нарешті, правильний потік, коли я знайшов зразок клієнта Javascript, я отримав правильний потік. Клієнт входить і встановлює маркер. Потім ваш веб-api споживає клієнт OIdc, який перевірить ваш маркер доступу до IdentityServer.

Підключаючись до магазинів та міграцій, спочатку я мав багато помилкових уявлень про міграції. У мене склалося враження, що запуск міграції генерував SQL з dll внутрішньо, замість того, щоб використовувати настроєний вами контекст, щоб з’ясувати, як створити SQL.

Існує два синтаксиси міграцій, які знають, який із них використовується вашим комп’ютером:

dotnet ef migrations add InitialIdentityServerMigration -c ApplicationDbContext

Add-Migration InitialIdentityServerDbMigration -c ApplicationDbContext

Я думаю, що параметр після Міграції - це ім’я, чому вам потрібне ім’я, я не впевнений, ApplicationDbContextце перший для коду DbContext, в якому ви хочете створити.

Міграції використовують деяку автоматичну магію, щоб виявити, що ви є рядком підключення від того, як налаштовано ваш запуск, я просто припустив, що він використовував підключення з Провідника серверів.

Якщо у вас кілька проектів, переконайтеся, що у вас є проект із ApplicationDbContext, встановленим для запуску.

При впровадженні авторизації та автентифікації є багато рухомих частин, сподіваємось, цей пост комусь допомагає. Найпростіший спосіб повною мірою зрозуміти автентифікацію - виділити їх приклади, щоб скласти все разом і переконатися, що ви прочитали документацію


ім’я після переміщення - це посилання, пов’язане з вашим випуском / змінами, які ви зробили. те саме ім'я буде використано для додавання сценарію міграції вгору та вниз.
Джей,

@Jay Дякую за роз'яснення
Джонні, 5

Конфігурація db контексту сервера Identity все ще не така хороша, як IdentityDbContext. створення власної реалізації - це біль. Зараз Identityserver 4, здається, не надто активний, щоб випускати нові оновлення після оновлення .core.
Джей,

3

ASP.NET Identity - це збірка таким чином, щоб автентифікувати вашу програму, будь то передавач чи основна автентифікація, вона надає нам готовий код для реєстрації користувачів, входу в систему, зміни пароля та всього іншого.

Тепер розглянемо, що у нас 10 різних додатків, і неможливо зробити одне і те ж у всіх 10 додатках. ця дуже крихка і дуже погана практика.

щоб вирішити цю проблему, ми можемо зробити централізацію нашої автентифікації та авторизації, тому всякий раз, коли будь-яка зміна з цим не вплине на всі наші 10 додатків.

Сервер ідентифікації надає вам можливість робити те саме. ми можемо створити один зразок веб-додатку, який щойно використовувався як служба посвідчення особи, і він перевірить вашого користувача та надасть деякий маркер доступу JWT.


2

Я завжди використовував вбудовану в ASP.NET Identity (і раніше Членство) авторизацію / автентифікацію, нещодавно я застосував Auth0 ( https://auth0.com ) і рекомендую це як щось інше, щоб спробувати.


Приклад ядра Auth0 .net досить швидкий і простий у реалізації, але використання всіх функцій вимагає неабиякої роботи, я впровадив Auth0, інтегруючи багато функцій, і він працює добре, але, як і всі ці речі, його потреби є трохи роботи та трохи розчарувань.
Марк Редман

Коли я отримаю одну автентифікацію, яка працює добре, я розміщу на ній глибоку відповідь. Минулого тижня я щойно працював над автентифікацією. І ніщо так не просувається вперед, як повинно бути
Джонні 5

0

Соціальні логіни не важко реалізувати за допомогою Identity, але є певна початкова настройка, і іноді кроки, які ви знайдете в Інтернеті в документах, не однакові, як правило, ви можете знайти довідку для цього в розділі розробників платформи, яку ви намагаєтесь налаштувати соціальні логіни для. Ідентичність - це заміна старої функціональності членства, знайденої у застарілих версіях .net framework. Те, що я виявив дивовижним, полягає в тому, що випадки використання крайових елементів, такі як передача вже наявного токена jwt до веб-API, ніде не розглядаються в прикладах онлайн навіть на pluralsight я впевнений, що для цього вам не потрібні власні повноваження маркера, але я не знайшов жодного прикладу про те, як передавати дані в get або post, які не стосуються самостійно розміщеного сервера.


можливо, ви після цього docs.identityserver.io/en/release/quickstarts/…
Джей,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.