Миграция проверки подлинности и Identity ASP.NET Core 2.0
ASP.NET Core 2.0 имеет новую модель для проверки подлинности и Identity упрощает настройку с помощью служб. ASP.NET приложения Core 1.x, использующие проверку подлинности или Identity можно обновить для использования новой модели, как описано ниже.
Обновление пространств имен
В версии 1.x такие классы IdentityRole
IdentityUser
были найдены в Microsoft.AspNetCore.Identity.EntityFrameworkCore
пространстве имен.
В 2.0 Microsoft.AspNetCore.Identity пространство имен стало новым home для нескольких таких классов. В коде по умолчанию Identity затронутые классы включают ApplicationUser
и Startup
. using
Настройте инструкции для разрешения затронутых ссылок.
ПО промежуточного слоя проверки подлинности и служб
В проектах 1.x проверка подлинности настраивается с помощью ПО промежуточного слоя. Метод ПО промежуточного слоя вызывается для каждой схемы проверки подлинности, которую требуется поддерживать.
Следующий пример 1.x настраивает проверку подлинности Facebook с помощью Identity Startup.cs
:
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory)
{
app.UseIdentity();
app.UseFacebookAuthentication(new FacebookOptions {
AppId = Configuration["auth:facebook:appid"],
AppSecret = Configuration["auth:facebook:appsecret"]
});
}
В проектах 2.0 проверка подлинности настраивается через службы. Каждая схема проверки подлинности регистрируется в методе ConfigureServices
Startup.cs
. Метод UseIdentity
заменяется UseAuthentication
на .
Следующий пример 2.0 настраивает проверку подлинности Facebook в Identity Startup.cs
:
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
// If you want to tweak Identity cookies, they're no longer part of IdentityOptions.
services.ConfigureApplicationCookie(options => options.LoginPath = "/Account/LogIn");
services.AddAuthentication()
.AddFacebook(options =>
{
options.AppId = Configuration["auth:facebook:appid"];
options.AppSecret = Configuration["auth:facebook:appsecret"];
});
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory) {
app.UseAuthentication();
}
Этот UseAuthentication
метод добавляет один компонент ПО промежуточного слоя проверки подлинности, который отвечает за автоматическую проверку подлинности и обработку запросов удаленной проверки подлинности. Он заменяет все отдельные компоненты по промежуточного слоя одним общим компонентом по промежуточного слоя.
Ниже приведены инструкции по миграции 2.0 для каждой основной схемы проверки подлинности.
CookieПроверка подлинности на основе
Выберите один из двух следующих вариантов и внесите необходимые изменения в Startup.cs
:
Использование файлов cookie с Identity
UseAuthentication
ЗаменитеUseIdentity
наConfigure
метод:app.UseAuthentication();
Вызовите метод в методе
AddIdentity
ConfigureServices
, чтобы добавить cookie службы проверки подлинности.При необходимости вызовите
ConfigureApplicationCookie
метод илиConfigureExternalCookie
метод в методеConfigureServices
, чтобы настроить Identitycookie параметры.services.AddIdentity<ApplicationUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); services.ConfigureApplicationCookie(options => options.LoginPath = "/Account/LogIn");
Использование файлов cookie без Identity
Замените
UseCookieAuthentication
вызов метода в методеUseAuthentication
следующимConfigure
:app.UseAuthentication();
AddAuthentication
Вызовите методы иAddCookie
методы в методеConfigureServices
:// If you don't want the cookie to be automatically authenticated and assigned to HttpContext.User, // remove the CookieAuthenticationDefaults.AuthenticationScheme parameter passed to AddAuthentication. services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Account/LogIn"; options.LogoutPath = "/Account/LogOff"; });
Проверка подлинности носителя JWT
Внесите следующие изменения в Startup.cs
:
Замените
UseJwtBearerAuthentication
вызов метода в методеUseAuthentication
следующимConfigure
:app.UseAuthentication();
AddJwtBearer
Вызов метода в методеConfigureServices
:services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Audience = "http://localhost:5001/"; options.Authority = "http://localhost:5000/"; });
Этот фрагмент кода не используется Identity, поэтому схема по умолчанию должна быть задана путем передачи
JwtBearerDefaults.AuthenticationScheme
вAddAuthentication
метод.
Проверка подлинности OpenID Connect (OIDC)
Внесите следующие изменения в Startup.cs
:
Замените
UseOpenIdConnectAuthentication
вызов метода в методеUseAuthentication
следующимConfigure
:app.UseAuthentication();
AddOpenIdConnect
Вызов метода в методеConfigureServices
:services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie() .AddOpenIdConnect(options => { options.Authority = Configuration["auth:oidc:authority"]; options.ClientId = Configuration["auth:oidc:clientid"]; });
Замените
PostLogoutRedirectUri
свойство в действииSignedOutRedirectUri
OpenIdConnectOptions
следующим:.AddOpenIdConnect(options => { options.SignedOutRedirectUri = "https://contoso.com"; });
Проверка подлинности Facebook
Внесите следующие изменения в Startup.cs
:
Замените
UseFacebookAuthentication
вызов метода в методеUseAuthentication
следующимConfigure
:app.UseAuthentication();
AddFacebook
Вызов метода в методеConfigureServices
:services.AddAuthentication() .AddFacebook(options => { options.AppId = Configuration["auth:facebook:appid"]; options.AppSecret = Configuration["auth:facebook:appsecret"]; });
Проверка подлинности Google
Внесите следующие изменения в Startup.cs
:
Замените
UseGoogleAuthentication
вызов метода в методеUseAuthentication
следующимConfigure
:app.UseAuthentication();
AddGoogle
Вызов метода в методеConfigureServices
:services.AddAuthentication() .AddGoogle(options => { options.ClientId = Configuration["auth:google:clientid"]; options.ClientSecret = Configuration["auth:google:clientsecret"]; });
Проверка подлинности учетной записи Майкрософт
Дополнительные сведения об проверке подлинности учетной записи Майкрософт см . в этой проблеме с GitHub.
Внесите следующие изменения в Startup.cs
:
Замените
UseMicrosoftAccountAuthentication
вызов метода в методеUseAuthentication
следующимConfigure
:app.UseAuthentication();
AddMicrosoftAccount
Вызов метода в методеConfigureServices
:services.AddAuthentication() .AddMicrosoftAccount(options => { options.ClientId = Configuration["auth:microsoft:clientid"]; options.ClientSecret = Configuration["auth:microsoft:clientsecret"]; });
Проверка подлинности Twitter
Внесите следующие изменения в Startup.cs
:
Замените
UseTwitterAuthentication
вызов метода в методеUseAuthentication
следующимConfigure
:app.UseAuthentication();
AddTwitter
Вызов метода в методеConfigureServices
:services.AddAuthentication() .AddTwitter(options => { options.ConsumerKey = Configuration["auth:twitter:consumerkey"]; options.ConsumerSecret = Configuration["auth:twitter:consumersecret"]; });
Настройка схем проверки подлинности по умолчанию
В версии 1.x AutomaticAuthenticate
AutomaticChallenge
AuthenticationOptions свойства базового класса должны быть заданы в одной схеме проверки подлинности. Не было хорошего способа применить это.
В версии 2.0 эти два свойства были удалены в качестве свойств в отдельном AuthenticationOptions
экземпляре. Их можно настроить в вызове AddAuthentication
метода в методе ConfigureServices
Startup.cs
:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme);
В приведенном выше фрагменте кода для схемы по умолчанию задано значение CookieAuthenticationDefaults.AuthenticationScheme
("Файлы cookie").
Кроме того, используйте перегруженную версию метода для задания нескольких AddAuthentication
свойств. В следующем перегруженном примере метода для схемы по умолчанию задано CookieAuthenticationDefaults.AuthenticationScheme
значение . Схема проверки подлинности может быть также указана в отдельных [Authorize]
атрибутах или политиках авторизации.
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});
Определите схему по умолчанию в версии 2.0, если одно из следующих условий имеет значение true:
- Вы хотите, чтобы пользователь автоматически вошел в систему
- Атрибут или политики авторизации используются
[Authorize]
без указания схем
Исключением из этого правила является AddIdentity
метод. Этот метод добавляет файлы cookie для вас и задает схемы проверки подлинности и вызовов по умолчанию для приложения cookieIdentityConstants.ApplicationScheme
. Кроме того, он задает схему входа по умолчанию во внешнюю cookieIdentityConstants.ExternalScheme
.
Использование расширений проверки подлинности HttpContext
Интерфейс IAuthenticationManager
является главной точкой входа в систему проверки подлинности 1.x. Он был заменен новым набором HttpContext
методов расширения в Microsoft.AspNetCore.Authentication
пространстве имен.
Например, проекты 1.x ссылались на Authentication
свойство:
// Clear the existing external cookie to ensure a clean login process
await HttpContext.Authentication.SignOutAsync(_externalCookieScheme);
В проектах 2.0 импортируйте Microsoft.AspNetCore.Authentication
пространство имен и удалите ссылки на Authentication
свойства:
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
Проверка подлинности Windows (HTTP.sys / IISIntegration)
Существует два варианта проверка подлинности Windows:
Узел разрешает только прошедшим проверку подлинности пользователям. Этот вариант не влияет на изменения версии 2.0.
Узел разрешает анонимным и прошедшим проверку подлинности пользователям. Этот вариант влияет на изменения версии 2.0. Например, приложение должно разрешить анонимным пользователям на уровне IIS или HTTP.sys, но авторизовать пользователей на уровне контроллера. В этом сценарии задайте схему по умолчанию в методе
Startup.ConfigureServices
.Для Microsoft.AspNetCore.Server.IISIntegration задайте схему
IISDefaults.AuthenticationScheme
по умолчанию следующим образом:using Microsoft.AspNetCore.Server.IISIntegration; services.AddAuthentication(IISDefaults.AuthenticationScheme);
Для Microsoft.AspNetCore.Server.HttpSys задайте схему
HttpSysDefaults.AuthenticationScheme
по умолчанию:using Microsoft.AspNetCore.Server.HttpSys; services.AddAuthentication(HttpSysDefaults.AuthenticationScheme);
Не удается установить схему по умолчанию, чтобы запретить запрос на авторизацию (вызов) работать со следующим исключением:
System.InvalidOperationException
: не указана проверка подлинностиScheme, и не было найдено DefaultChallengeScheme.
Дополнительные сведения см. в статье Настройка проверки подлинности Windows в ASP.NET Core.
Экземпляры IdentityCookieOptions
Побочным эффектом изменений версии 2.0 является переход на использование именованных параметров вместо cookie экземпляров параметров. Возможность настраивать Identitycookie имена схем удаляется.
Например, проекты 1.x используют внедрение конструктора для передачи IdentityCookieOptions
параметра AccountController.cs
в и ManageController.cs
. Доступ к внешней cookie схеме проверки подлинности осуществляется из предоставленного экземпляра:
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IOptions<IdentityCookieOptions> identityCookieOptions,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory)
{
_userManager = userManager;
_signInManager = signInManager;
_externalCookieScheme = identityCookieOptions.Value.ExternalCookieAuthenticationScheme;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
}
Внедрение указанного выше конструктора становится ненужным в проектах 2.0, а _externalCookieScheme
поле можно удалить:
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
}
Проекты 1.x использовали _externalCookieScheme
поле следующим образом:
// Clear the existing external cookie to ensure a clean login process
await HttpContext.Authentication.SignOutAsync(_externalCookieScheme);
В проектах 2.0 замените предыдущий код следующим кодом. Константу IdentityConstants.ExternalScheme
можно использовать напрямую.
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
Устраните только что добавленный SignOutAsync
вызов, импортируя следующее пространство имен:
using Microsoft.AspNetCore.Authentication;
Добавление свойств навигации IdentityUser POCO
Свойства навигации Entity Framework (EF) Core базового IdentityUser
POCO (обычный старый объект CLR) были удалены. Если проект 1.x использовал эти свойства, вручную добавьте их в проект 2.0:
/// <summary>
/// Navigation property for the roles this user belongs to.
/// </summary>
public virtual ICollection<IdentityUserRole<int>> Roles { get; } = new List<IdentityUserRole<int>>();
/// <summary>
/// Navigation property for the claims this user possesses.
/// </summary>
public virtual ICollection<IdentityUserClaim<int>> Claims { get; } = new List<IdentityUserClaim<int>>();
/// <summary>
/// Navigation property for this users login accounts.
/// </summary>
public virtual ICollection<IdentityUserLogin<int>> Logins { get; } = new List<IdentityUserLogin<int>>();
Чтобы предотвратить дублирование внешних ключей при выполнении EF Core миграций, добавьте в метод класса IdentityDbContext
OnModelCreating
следующий код (после base.OnModelCreating();
вызова):
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Core Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Core Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
builder.Entity<ApplicationUser>()
.HasMany(e => e.Claims)
.WithOne()
.HasForeignKey(e => e.UserId)
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
builder.Entity<ApplicationUser>()
.HasMany(e => e.Logins)
.WithOne()
.HasForeignKey(e => e.UserId)
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
builder.Entity<ApplicationUser>()
.HasMany(e => e.Roles)
.WithOne()
.HasForeignKey(e => e.UserId)
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
}
Замена GetExternalAuthenticationSchemes
Синхронный метод GetExternalAuthenticationSchemes
был удален в пользу асинхронной версии. В проектах 1.x есть следующий код:Controllers/ManageController.cs
var otherLogins = _signInManager.GetExternalAuthenticationSchemes().Where(auth => userLogins.All(ul => auth.AuthenticationScheme != ul.LoginProvider)).ToList();
Этот метод также отображается:Views/Account/Login.cshtml
@{
var loginProviders = SignInManager.GetExternalAuthenticationSchemes().ToList();
if (loginProviders.Count == 0)
{
<div>
<p>
There are no external authentication services configured. See <a href="https://go.microsoft.com/fwlink/?LinkID=532715">this article</a>
for details on setting up this ASP.NET application to support logging in via external services.
</p>
</div>
}
else
{
<form asp-controller="Account" asp-action="ExternalLogin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal">
<div>
<p>
@foreach (var provider in loginProviders)
{
<button type="submit" class="btn btn-default" name="provider" value="@provider.AuthenticationScheme" title="Log in using your @provider.DisplayName account">@provider.AuthenticationScheme</button>
}
</p>
</div>
</form>
}
}
В проектах 2.0 используйте GetExternalAuthenticationSchemesAsync метод. Это изменение ManageController.cs
напоминает следующий код:
var schemes = await _signInManager.GetExternalAuthenticationSchemesAsync();
var otherLogins = schemes.Where(auth => userLogins.All(ul => auth.Name != ul.LoginProvider)).ToList();
В Login.cshtml
, доступ к свойствуAuthenticationScheme
, к который обращается в циклеforeach
, изменяется:Name
@{
var loginProviders = (await SignInManager.GetExternalAuthenticationSchemesAsync()).ToList();
if (loginProviders.Count == 0)
{
<div>
<p>
There are no external authentication services configured. See <a href="https://go.microsoft.com/fwlink/?LinkID=532715">this article</a>
for details on setting up this ASP.NET application to support logging in via external services.
</p>
</div>
}
else
{
<form asp-controller="Account" asp-action="ExternalLogin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal">
<div>
<p>
@foreach (var provider in loginProviders)
{
<button type="submit" class="btn btn-default" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
}
</p>
</div>
</form>
}
}
Изменение свойства ManageLoginsViewModel
Объект ManageLoginsViewModel
используется в ManageLogins
действии ManageController.cs
. В проектах 1.x возвращается IList<AuthenticationDescription>
тип возвращаемого OtherLogins
свойства объекта. Для этого типа возврата требуется импорт Microsoft.AspNetCore.Http.Authentication
:
using System.Collections.Generic;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.AspNetCore.Identity;
namespace AspNetCoreDotNetCore1App.Models.ManageViewModels
{
public class ManageLoginsViewModel
{
public IList<UserLoginInfo> CurrentLogins { get; set; }
public IList<AuthenticationDescription> OtherLogins { get; set; }
}
}
В проектах 2.0 возвращаемый тип изменяется IList<AuthenticationScheme>
на . Этот новый тип возвращаемого Microsoft.AspNetCore.Http.Authentication
значения требует замены импорта импортом Microsoft.AspNetCore.Authentication
.
using System.Collections.Generic;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
namespace AspNetCoreDotNetCore2App.Models.ManageViewModels
{
public class ManageLoginsViewModel
{
public IList<UserLoginInfo> CurrentLogins { get; set; }
public IList<AuthenticationScheme> OtherLogins { get; set; }
}
}
Дополнительные ресурсы
Дополнительные сведения см. в статье "Обсуждение проверки подлинности 2.0 " на сайте GitHub.
ASP.NET Core