Migrasikan autentikasi dan Identity ke ASP.NET Core 2.0
Oleh Scott Addie dan Hao Kung
ASP.NET Core 2.0 memiliki model baru untuk autentikasi dan Identity yang menyederhanakan konfigurasi dengan menggunakan layanan. ASP.NET aplikasi Core 1.x yang menggunakan autentikasi atau Identity dapat diperbarui untuk menggunakan model baru seperti yang diuraikan di bawah ini.
Memperbarui namespace layanan
Dalam 1.x, kelas seperti IdentityRole
itu dan IdentityUser
ditemukan di Microsoft.AspNetCore.Identity.EntityFrameworkCore
namespace layanan.
Pada 2.0, Microsoft.AspNetCore.Identity namespace menjadi yang baru home untuk beberapa kelas tersebut. Dengan kode default Identity , kelas yang terpengaruh termasuk ApplicationUser
dan Startup
. Sesuaikan pernyataan Anda using
untuk menyelesaikan referensi yang terpengaruh.
Middleware dan layanan Autentikasi
Dalam proyek 1.x, autentikasi dikonfigurasi melalui middleware. Metode middleware dipanggil untuk setiap skema autentikasi yang ingin Anda dukung.
Contoh 1.x berikut mengonfigurasi autentikasi Facebook dengan Identity di 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"]
});
}
Dalam proyek 2.0, autentikasi dikonfigurasi melalui layanan. Setiap skema autentikasi terdaftar dalam ConfigureServices
metode Startup.cs
. Metode UseIdentity
ini diganti dengan UseAuthentication
.
Contoh 2.0 berikut mengonfigurasi autentikasi Facebook dengan Identity di 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();
}
Metode ini UseAuthentication
menambahkan satu komponen middleware autentikasi, yang bertanggung jawab atas autentikasi otomatis dan penanganan permintaan autentikasi jarak jauh. Ini menggantikan semua komponen middleware individual dengan satu komponen middleware umum.
Di bawah ini adalah instruksi migrasi 2.0 untuk setiap skema autentikasi utama.
Cookieautentikasi berbasis
Pilih salah satu dari dua opsi di bawah ini, dan buat perubahan yang diperlukan di Startup.cs
:
Menggunakan cookie dengan Identity
Ganti
UseIdentity
denganUseAuthentication
dalamConfigure
metode :app.UseAuthentication();
Panggil
AddIdentity
metode dalamConfigureServices
metode untuk menambahkan cookie layanan autentikasi.Secara opsional, panggil
ConfigureApplicationCookie
metode atauConfigureExternalCookie
dalamConfigureServices
metode untuk mengubah Identitycookie pengaturan.services.AddIdentity<ApplicationUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); services.ConfigureApplicationCookie(options => options.LoginPath = "/Account/LogIn");
Menggunakan cookie tanpa Identity
UseCookieAuthentication
Ganti panggilan metode dalamConfigure
metode denganUseAuthentication
:app.UseAuthentication();
Panggil
AddAuthentication
metode danAddCookie
dalamConfigureServices
metode :// 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"; });
Autentikasi Pembawa JWT
Buat perubahan berikut di Startup.cs
:
UseJwtBearerAuthentication
Ganti panggilan metode dalamConfigure
metode denganUseAuthentication
:app.UseAuthentication();
Panggil
AddJwtBearer
metode dalamConfigureServices
metode :services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Audience = "http://localhost:5001/"; options.Authority = "http://localhost:5000/"; });
Cuplikan kode ini tidak menggunakan Identity, sehingga skema default harus diatur dengan meneruskan
JwtBearerDefaults.AuthenticationScheme
keAddAuthentication
metode .
Autentikasi OpenID Connect (OIDC)
Buat perubahan berikut di Startup.cs
:
UseOpenIdConnectAuthentication
Ganti panggilan metode dalamConfigure
metode denganUseAuthentication
:app.UseAuthentication();
Panggil
AddOpenIdConnect
metode dalamConfigureServices
metode :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
Ganti properti dalamOpenIdConnectOptions
tindakan denganSignedOutRedirectUri
:.AddOpenIdConnect(options => { options.SignedOutRedirectUri = "https://contoso.com"; });
Autentikasi Facebook
Buat perubahan berikut di Startup.cs
:
UseFacebookAuthentication
Ganti panggilan metode dalamConfigure
metode denganUseAuthentication
:app.UseAuthentication();
Panggil
AddFacebook
metode dalamConfigureServices
metode :services.AddAuthentication() .AddFacebook(options => { options.AppId = Configuration["auth:facebook:appid"]; options.AppSecret = Configuration["auth:facebook:appsecret"]; });
Autentikasi Google
Buat perubahan berikut di Startup.cs
:
UseGoogleAuthentication
Ganti panggilan metode dalamConfigure
metode denganUseAuthentication
:app.UseAuthentication();
Panggil
AddGoogle
metode dalamConfigureServices
metode :services.AddAuthentication() .AddGoogle(options => { options.ClientId = Configuration["auth:google:clientid"]; options.ClientSecret = Configuration["auth:google:clientsecret"]; });
Autentikasi Akun Microsoft
Untuk informasi selengkapnya tentang autentikasi akun Microsoft, lihat masalah GitHub ini.
Buat perubahan berikut di Startup.cs
:
UseMicrosoftAccountAuthentication
Ganti panggilan metode dalamConfigure
metode denganUseAuthentication
:app.UseAuthentication();
Panggil
AddMicrosoftAccount
metode dalamConfigureServices
metode :services.AddAuthentication() .AddMicrosoftAccount(options => { options.ClientId = Configuration["auth:microsoft:clientid"]; options.ClientSecret = Configuration["auth:microsoft:clientsecret"]; });
Autentikasi Twitter
Buat perubahan berikut di Startup.cs
:
UseTwitterAuthentication
Ganti panggilan metode dalamConfigure
metode denganUseAuthentication
:app.UseAuthentication();
Panggil
AddTwitter
metode dalamConfigureServices
metode :services.AddAuthentication() .AddTwitter(options => { options.ConsumerKey = Configuration["auth:twitter:consumerkey"]; options.ConsumerSecret = Configuration["auth:twitter:consumersecret"]; });
Mengatur skema autentikasi default
Dalam 1.x, AutomaticAuthenticate
properti dan AutomaticChallenge
kelas AuthenticationOptions dasar dimaksudkan untuk diatur pada skema autentikasi tunggal. Tidak ada cara yang baik untuk menegakkan ini.
Dalam 2.0, kedua properti ini telah dihapus sebagai properti pada instans individual AuthenticationOptions
. Mereka dapat dikonfigurasi dalam AddAuthentication
panggilan metode dalam ConfigureServices
metode :Startup.cs
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme);
Dalam cuplikan kode sebelumnya, skema default diatur ke CookieAuthenticationDefaults.AuthenticationScheme
("Cookie").
Atau, gunakan versi AddAuthentication
metode yang kelebihan beban untuk mengatur lebih dari satu properti. Dalam contoh metode kelebihan beban berikut, skema default diatur ke CookieAuthenticationDefaults.AuthenticationScheme
. Skema autentikasi dapat ditentukan secara alternatif dalam atribut atau kebijakan otorisasi individual [Authorize]
Anda.
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});
Tentukan skema default di 2.0 jika salah satu kondisi berikut ini benar:
- Anda ingin pengguna masuk secara otomatis
- Anda menggunakan
[Authorize]
atribut atau kebijakan otorisasi tanpa menentukan skema
Pengecualian untuk aturan ini adalah AddIdentity
metode . Metode ini menambahkan cookie untuk Anda dan mengatur skema autentikasi dan tantangan default ke aplikasi cookieIdentityConstants.ApplicationScheme
. Selain itu, ini mengatur skema masuk default ke eksternal cookieIdentityConstants.ExternalScheme
.
Menggunakan ekstensi autentikasi HttpContext
Antarmuka IAuthenticationManager
adalah titik masuk utama ke dalam sistem autentikasi 1.x. Ini telah diganti dengan sekumpulan HttpContext
metode ekstensi baru di Microsoft.AspNetCore.Authentication
namespace layanan.
Misalnya, proyek 1.x mereferensikan Authentication
properti:
// Clear the existing external cookie to ensure a clean login process
await HttpContext.Authentication.SignOutAsync(_externalCookieScheme);
Dalam proyek 2.0, impor Microsoft.AspNetCore.Authentication
namespace layanan, dan hapus Authentication
referensi properti:
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
Autentikasi Windows (HTTP.sys /IISIntegration)
Ada dua variasi autentikasi Windows:
Host hanya mengizinkan pengguna yang diautentikasi. Variasi ini tidak terpengaruh oleh perubahan 2.0.
Host memungkinkan pengguna anonim dan terautentikasi. Variasi ini dipengaruhi oleh perubahan 2.0. Misalnya, aplikasi harus mengizinkan pengguna anonim di lapisan IIS atau HTTP.sys tetapi mengotorisasi pengguna di tingkat pengontrol. Dalam skenario ini, atur skema default dalam
Startup.ConfigureServices
metode .Untuk Microsoft.AspNetCore.Server.IISIntegration, atur skema default ke
IISDefaults.AuthenticationScheme
:using Microsoft.AspNetCore.Server.IISIntegration; services.AddAuthentication(IISDefaults.AuthenticationScheme);
Untuk Microsoft.AspNetCore.Server.HttpSys, atur skema default ke
HttpSysDefaults.AuthenticationScheme
:using Microsoft.AspNetCore.Server.HttpSys; services.AddAuthentication(HttpSysDefaults.AuthenticationScheme);
Kegagalan untuk mengatur skema default mencegah permintaan otorisasi (tantangan) bekerja dengan pengecualian berikut:
System.InvalidOperationException
: Tidak ada authenticationScheme yang ditentukan, dan tidak ada DefaultChallengeScheme yang ditemukan.
Untuk informasi selengkapnya, lihat Mengonfigurasi Autentikasi Windows di ASP.NET Core.
Instans IdentityCookieOptions
Efek samping dari perubahan 2.0 adalah beralih menggunakan opsi bernama alih-alih cookie instans opsi. Kemampuan untuk menyesuaikan Identitycookie nama skema dihapus.
Misalnya, proyek 1.x menggunakan injeksi konstruktor untuk meneruskan IdentityCookieOptions
parameter ke dalam AccountController.cs
dan ManageController.cs
. Skema autentikasi eksternal cookie diakses dari instans yang disediakan:
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>();
}
Injeksi konstruktor yang disebutkan di atas menjadi tidak perlu dalam proyek 2.0, dan _externalCookieScheme
bidang dapat dihapus:
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>();
}
Proyek 1.x menggunakan _externalCookieScheme
bidang sebagai berikut:
// Clear the existing external cookie to ensure a clean login process
await HttpContext.Authentication.SignOutAsync(_externalCookieScheme);
Dalam proyek 2.0, ganti kode sebelumnya dengan yang berikut ini. Konstanta IdentityConstants.ExternalScheme
dapat digunakan secara langsung.
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
Atasi panggilan yang baru ditambahkan SignOutAsync
dengan mengimpor namespace berikut:
using Microsoft.AspNetCore.Authentication;
Menambahkan properti navigasi POCO IdentityUser
Properti navigasi Core Entity Framework (EF) dari POCO dasar IdentityUser
(Objek CLR Lama Biasa) telah dihapus. Jika proyek 1.x Anda menggunakan properti ini, tambahkan kembali secara manual ke proyek 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>>();
Untuk mencegah kunci asing duplikat saat menjalankan EF Core Migrasi, tambahkan yang berikut ini ke metode kelas OnModelCreating
Anda IdentityDbContext
(setelah base.OnModelCreating();
panggilan):
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);
}
Mengganti GetExternalAuthenticationSchemes
Metode sinkron GetExternalAuthenticationSchemes
dihapus demi versi asinkron. Proyek 1.x memiliki kode berikut di Controllers/ManageController.cs
:
var otherLogins = _signInManager.GetExternalAuthenticationSchemes().Where(auth => userLogins.All(ul => auth.AuthenticationScheme != ul.LoginProvider)).ToList();
Metode ini juga muncul di 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>
}
}
Dalam proyek 2.0, gunakan metode .GetExternalAuthenticationSchemesAsync Perubahan menyerupan ManageController.cs
kode berikut:
var schemes = await _signInManager.GetExternalAuthenticationSchemesAsync();
var otherLogins = schemes.Where(auth => userLogins.All(ul => auth.Name != ul.LoginProvider)).ToList();
Dalam Login.cshtml
, properti yang AuthenticationScheme
diakses dalam perulangan foreach
berubah menjadi 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>
}
}
Perubahan properti ManageLoginsViewModel
Objek ManageLoginsViewModel
digunakan dalam ManageLogins
tindakan ManageController.cs
. Dalam proyek 1.x, jenis pengembalian properti objek OtherLogins
adalah IList<AuthenticationDescription>
. Jenis pengembalian ini memerlukan impor 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; }
}
}
Dalam proyek 2.0, jenis pengembalian berubah menjadi IList<AuthenticationScheme>
. Jenis pengembalian baru ini memerlukan mengganti Microsoft.AspNetCore.Http.Authentication
impor dengan Microsoft.AspNetCore.Authentication
impor.
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; }
}
}
Sumber Daya Tambahan:
Untuk informasi selengkapnya, lihat masalah Diskusi untuk Auth 2.0 di GitHub.
ASP.NET Core