Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Tarafından Rick Anderson
Bu makalede şunların nasıl yapıldığını gösterir:
- ASP.NET Core web uygulamasına özel kullanıcı verileri ekleme.
- Özel kullanıcı veri modelini özniteliğiyle işaretleyip PersonalDataAttribute otomatik olarak indirilip silinebilmesini sağlayın. Verilerin indirilip silinebilmesi , GDPR gereksinimlerini karşılamaya yardımcı olur.
Proje örneği bir Razor Pages web uygulamasından oluşturulur, ancak yönergeler ASP.NET Core MVC web uygulaması için benzerdir.
Örnek kodu görüntüleme veya indirme (indirme)
Prerequisites
Razor Web uygulaması oluşturma
- Visual Studio Dosya menüsünden, Yeni>Proje'yi seçin. İndirme örnek kodunun ad alanıyla eşleşmesini istiyorsanız projeyi WebApp1 olarak adlandırın.
- ASP.NET Çekirdek Web Uygulaması>Tamam'ı seçin
- Web Uygulaması>Tamam'ı seçin
- Projeyi derleyin ve çalıştırın.
Scaffolder'ı Identity çalıştır
- Çözüm Gezgini, Projeye Yeni İskeleli Öğe>>sağ tıklayın.
- İskelet Ekle iletişim kutusunun sol bölmesinden, Identity'yi seçin>.
-
Ekle Identity iletişim kutusunda aşağıdaki seçenekler:
- Var olan düzen dosyasını seçin
~/Pages/Shared/_Layout.cshtml - Geçersiz kılmak için aşağıdaki dosyaları seçin:
- Account/Register
- Account/Manage/Index
- + Yeni bir Veri bağlam sınıfı oluşturmak için düğmesini seçin. Türü kabul edin (Projenin adı WebApp1 ise WebApp1.Models.WebApp1Context).
- + Yeni bir Kullanıcı sınıfı oluşturmak için düğmesini seçin. Proje WebApp1 olarak adlandırılmışsa, türü WebApp1User olarak kabul edin ve >.
- Var olan düzen dosyasını seçin
- Add (Ekle) seçeneğini belirleyin.
Aşağıdaki adımları gerçekleştirmek için Geçişler, UseAuthentication ve düzen yönergelerini izleyin:
- Geçiş oluşturun ve veritabanını güncelleştirin.
-
UseAuthenticationöğesiniProgram.csöğesine ekleyin - Düzen dosyasına
<partial name="_LoginPartial" />ekleyin. - Uygulamayı test edin:
- Kullanıcı kaydetme
- Yeni kullanıcı adını seçin ( Oturum Kapatma bağlantısının yanında). Kullanıcı adını ve diğer bağlantıları göstermek için pencereyi genişletmeniz veya gezinti çubuğu simgesini seçmeniz gerekebilir.
- Kişisel Veriler sekmesini seçin.
-
İndir düğmesini seçin ve dosyayı incelediniz
PersonalData.json. - Oturum açmış kullanıcıyı silen Sil düğmesini test edin.
Db'ye Identity özel kullanıcı verileri ekleme
IdentityUser Türetilmiş sınıfı özel özelliklerle güncelleştirin. Projeyi WebApp1 olarak adlandırdıysanız, dosya olarak adlandırılır Areas/Identity/Data/WebApp1User.cs. Dosyayı aşağıdaki kodla güncelleştirin:
using Microsoft.AspNetCore.Identity;
namespace WebApp1.Areas.Identity.Data;
public class WebApp1User : IdentityUser
{
[PersonalData]
public string? Name { get; set; }
[PersonalData]
public DateTime DOB { get; set; }
}
PersonalData özniteliğine sahip özellikler şunlardır:
- Silindiğinde
Areas/Identity/Pages/Account/Manage/DeletePersonalData.cshtmlRazor SayfaUserManager.Deleteçalıştırır. - İndirilen verilere
Areas/Identity/Pages/Account/Manage/DownloadPersonalData.cshtmlRazor Sayfa tarafından eklenmiştir.
Sayfayı Account/Manage/Index.cshtml güncelleştirme
InputModel öğesini Areas/Identity/Pages/Account/Manage/Index.cshtml.cs içindeki aşağıdaki vurgulanmış kodla güncelleyin.
public class IndexModel : PageModel
{
private readonly UserManager<WebApp1User> _userManager;
private readonly SignInManager<WebApp1User> _signInManager;
public IndexModel(
UserManager<WebApp1User> userManager,
SignInManager<WebApp1User> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public string Username { get; set; }
// Remaining API warnings ommited.
[TempData]
public string StatusMessage { get; set; }
[BindProperty]
public InputModel Input { get; set; }
public class InputModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Full name")]
public string Name { get; set; }
[Required]
[Display(Name = "Birth Date")]
[DataType(DataType.Date)]
public DateTime DOB { get; set; }
[Phone]
[Display(Name = "Phone number")]
public string PhoneNumber { get; set; }
}
private async Task LoadAsync(WebApp1User user)
{
var userName = await _userManager.GetUserNameAsync(user);
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
Username = userName;
Input = new InputModel
{
Name = user.Name,
DOB = user.DOB,
PhoneNumber = phoneNumber
};
}
public async Task<IActionResult> OnGetAsync()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
await LoadAsync(user);
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
if (!ModelState.IsValid)
{
await LoadAsync(user);
return Page();
}
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
if (Input.PhoneNumber != phoneNumber)
{
var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
if (!setPhoneResult.Succeeded)
{
StatusMessage = "Unexpected error when trying to set phone number.";
return RedirectToPage();
}
}
if (Input.Name != user.Name)
{
user.Name = Input.Name;
}
if (Input.DOB != user.DOB)
{
user.DOB = Input.DOB;
}
await _userManager.UpdateAsync(user);
await _signInManager.RefreshSignInAsync(user);
StatusMessage = "Your profile has been updated";
return RedirectToPage();
}
}
öğesini Areas/Identity/Pages/Account/Manage/Index.cshtml aşağıdaki vurgulanmış işaretlemeyle güncelleştirin:
@page
@model IndexModel
@{
ViewData["Title"] = "Profile";
ViewData["ActivePage"] = ManageNavPages.Index;
}
<h3>@ViewData["Title"]</h3>
<partial name="_StatusMessage" for="StatusMessage" />
<div class="row">
<div class="col-md-6">
<form id="profile-form" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-floating">
<input asp-for="Username" class="form-control" disabled />
<label asp-for="Username" class="form-label"></label>
</div>
<div class="form-floating">
<input asp-for="Input.Name" class="form-control" />
<label asp-for="Input.Name" class="form-label"></label>
</div>
<div class="form-floating">
<input asp-for="Input.DOB" class="form-control" />
<label asp-for="Input.DOB" class="form-label"></label>
</div>
<div class="form-floating">
<input asp-for="Input.PhoneNumber" class="form-control" />
<label asp-for="Input.PhoneNumber" class="form-label"></label>
<span asp-validation-for="Input.PhoneNumber" class="text-danger"></span>
</div>
<button id="update-profile-button" type="submit" class="w-100 btn btn-lg btn-primary">Save</button>
</form>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Sayfayı Account/Register.cshtml güncelleştirme
InputModel öğesini Areas/Identity/Pages/Account/Register.cshtml.cs içindeki aşağıdaki vurgulanmış kodla güncelleyin.
public class RegisterModel : PageModel
{
private readonly SignInManager<WebApp1User> _signInManager;
private readonly UserManager<WebApp1User> _userManager;
private readonly IUserStore<WebApp1User> _userStore;
private readonly IUserEmailStore<WebApp1User> _emailStore;
private readonly ILogger<RegisterModel> _logger;
private readonly IEmailSender _emailSender;
public RegisterModel(
UserManager<WebApp1User> userManager,
IUserStore<WebApp1User> userStore,
SignInManager<WebApp1User> signInManager,
ILogger<RegisterModel> logger,
IEmailSender emailSender)
{
_userManager = userManager;
_userStore = userStore;
_emailStore = GetEmailStore();
_signInManager = signInManager;
_logger = logger;
_emailSender = emailSender;
}
/// <summary>
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
[BindProperty]
public InputModel Input { get; set; }
// Remaining API warnings ommited.
public string ReturnUrl { get; set; }
public IList<AuthenticationScheme> ExternalLogins { get; set; }
public class InputModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Full name")]
public string Name { get; set; }
[Required]
[Display(Name = "Birth Date")]
[DataType(DataType.Date)]
public DateTime DOB { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
public async Task OnGetAsync(string returnUrl = null)
{
ReturnUrl = returnUrl;
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
}
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
if (ModelState.IsValid)
{
var user = CreateUser();
user.Name = Input.Name;
user.DOB = Input.DOB;
await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var userId = await _userManager.GetUserIdAsync(user);
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
if (_userManager.Options.SignIn.RequireConfirmedAccount)
{
return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl });
}
else
{
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
private WebApp1User CreateUser()
{
try
{
return Activator.CreateInstance<WebApp1User>();
}
catch
{
throw new InvalidOperationException($"Can't create an instance of '{nameof(WebApp1User)}'. " +
$"Ensure that '{nameof(WebApp1User)}' is not an abstract class and has a parameterless constructor, or alternatively " +
$"override the register page in /Areas/Identity/Pages/Account/Register.cshtml");
}
}
private IUserEmailStore<WebApp1User> GetEmailStore()
{
if (!_userManager.SupportsUserEmail)
{
throw new NotSupportedException("The default UI requires a user store with email support.");
}
return (IUserEmailStore<WebApp1User>)_userStore;
}
}
}
öğesini Areas/Identity/Pages/Account/Register.cshtml aşağıdaki vurgulanmış işaretlemeyle güncelleştirin:
@page
@model RegisterModel
@{
ViewData["Title"] = "Register";
}
<h1>@ViewData["Title"]</h1>
<div class="row">
<div class="col-md-4">
<form id="registerForm" asp-route-returnUrl="@Model.ReturnUrl" method="post">
<h2>Create a new account.</h2>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-floating">
<input asp-for="Input.Name" class="form-control" />
<label asp-for="Input.Name"></label>
<span asp-validation-for="Input.Name" class="text-danger"></span>
</div>
<div class="form-floating">
<input asp-for="Input.DOB" class="form-control" />
<label asp-for="Input.DOB"></label>
<span asp-validation-for="Input.DOB" class="text-danger"></span>
</div>
<div class="form-floating">
<input asp-for="Input.Email" class="form-control" autocomplete="username" aria-required="true" />
<label asp-for="Input.Email"></label>
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-floating">
<input asp-for="Input.Password" class="form-control" autocomplete="new-password" aria-required="true" />
<label asp-for="Input.Password"></label>
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-floating">
<input asp-for="Input.ConfirmPassword" class="form-control" autocomplete="new-password" aria-required="true" />
<label asp-for="Input.ConfirmPassword"></label>
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div>
<button id="registerSubmit" type="submit" class="w-100 btn btn-lg btn-primary">Register</button>
</form>
</div>
<div class="col-md-6 col-md-offset-2">
<section>
<h3>Use another service to register.</h3>
<hr />
@{
if ((Model.ExternalLogins?.Count ?? 0) == 0)
{
<div>
<p>
There are no external authentication services configured. See this <a href="https://go.microsoft.com/fwlink/?LinkID=532715">article
about setting up this ASP.NET application to support logging in via external services</a>.
</p>
</div>
}
else
{
<form id="external-account" asp-page="./ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" method="post" class="form-horizontal">
<div>
<p>
@foreach (var provider in Model.ExternalLogins!)
{
<button type="submit" class="btn btn-primary" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
}
</p>
</div>
</form>
}
}
</section>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Projeyi oluşturun.
Düzeni güncelleştirme
Her sayfaya oturum açma ve oturum kapatma bağlantıları ekleme yönergeleri için bkz . Düzen değişiklikleri .
Özel kullanıcı verileri için geçiş ekleme
Visual Studio Paket Yöneticisi Konsolu'nda:
Add-Migration CustomUserData
Update-Database
Özel kullanıcı verilerini oluşturmayı, görüntülemeyi, indirmeyi, silmeyi test edin
Uygulamayı test edin:
- Yeni bir kullanıcı kaydedin.
- Sayfadaki özel kullanıcı verilerini
/Identity/Account/Managegörüntüleyin. - Kullanıcıların kişisel verilerini sayfadan
/Identity/Account/Manage/PersonalDataindirin ve görüntüleyin.
Razor Web uygulaması oluşturma
- Visual Studio Dosya menüsünden, Yeni>Proje'yi seçin. İndirme örnek kodunun ad alanıyla eşleşmesini istiyorsanız projeyi WebApp1 olarak adlandırın.
- ASP.NET Çekirdek Web Uygulaması>Tamam'ı seçin
- Web Uygulaması>Tamam'ı seçin
- Projeyi derleyin ve çalıştırın.
Scaffolder'ı Identity çalıştır
- Çözüm Gezgini, Projeye Yeni İskeleli Öğe>>sağ tıklayın.
- İskelet Ekle iletişim kutusunun sol bölmesinden, Identity'yi seçin>.
-
Ekle Identity iletişim kutusunda aşağıdaki seçenekler:
- Var olan düzen dosyasını seçin
~/Pages/Shared/_Layout.cshtml - Geçersiz kılmak için aşağıdaki dosyaları seçin:
- Account/Register
- Account/Manage/Index
- + Yeni bir Veri bağlam sınıfı oluşturmak için düğmesini seçin. Türü kabul edin (Projenin adı WebApp1 ise WebApp1.Models.WebApp1Context).
- + Yeni bir Kullanıcı sınıfı oluşturmak için düğmesini seçin. Proje WebApp1 olarak adlandırılmışsa, türü WebApp1User olarak kabul edin ve >.
- Var olan düzen dosyasını seçin
- Add (Ekle) seçeneğini belirleyin.
Aşağıdaki adımları gerçekleştirmek için Geçişler, UseAuthentication ve düzen yönergelerini izleyin:
- Geçiş oluşturun ve veritabanını güncelleştirin.
-
UseAuthentication'yiStartup.Configure'ye ekle. - Düzen dosyasına
<partial name="_LoginPartial" />ekleyin. - Uygulamayı test edin:
- Kullanıcı kaydetme
- Yeni kullanıcı adını seçin ( Oturum Kapatma bağlantısının yanında). Kullanıcı adını ve diğer bağlantıları göstermek için pencereyi genişletmeniz veya gezinti çubuğu simgesini seçmeniz gerekebilir.
- Kişisel Veriler sekmesini seçin.
-
İndir düğmesini seçin ve dosyayı incelediniz
PersonalData.json. - Oturum açmış kullanıcıyı silen Sil düğmesini test edin.
Db'ye Identity özel kullanıcı verileri ekleme
IdentityUser Türetilmiş sınıfı özel özelliklerle güncelleştirin. Projeyi WebApp1 olarak adlandırdıysanız, dosya olarak adlandırılır Areas/Identity/Data/WebApp1User.cs. Dosyayı aşağıdaki kodla güncelleştirin:
using System;
using Microsoft.AspNetCore.Identity;
namespace WebApp1.Areas.Identity.Data
{
public class WebApp1User : IdentityUser
{
[PersonalData]
public string Name { get; set; }
[PersonalData]
public DateTime DOB { get; set; }
}
}
PersonalData özniteliğine sahip özellikler şunlardır:
- Silindiğinde
Areas/Identity/Pages/Account/Manage/DeletePersonalData.cshtmlRazor SayfaUserManager.Deleteçalıştırır. - İndirilen verilere
Areas/Identity/Pages/Account/Manage/DownloadPersonalData.cshtmlRazor Sayfa tarafından eklenmiştir.
Account/Manage/Index.cshtml sayfasını güncelleştirme
InputModel öğesini Areas/Identity/Pages/Account/Manage/Index.cshtml.cs içindeki aşağıdaki vurgulanmış kodla güncelleyin.
public partial class IndexModel : PageModel
{
private readonly UserManager<WebApp1User> _userManager;
private readonly SignInManager<WebApp1User> _signInManager;
public IndexModel(
UserManager<WebApp1User> userManager,
SignInManager<WebApp1User> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
public string Username { get; set; }
[TempData]
public string StatusMessage { get; set; }
[BindProperty]
public InputModel Input { get; set; }
public class InputModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Full name")]
public string Name { get; set; }
[Required]
[Display(Name = "Birth Date")]
[DataType(DataType.Date)]
public DateTime DOB { get; set; }
[Phone]
[Display(Name = "Phone number")]
public string PhoneNumber { get; set; }
}
private async Task LoadAsync(WebApp1User user)
{
var userName = await _userManager.GetUserNameAsync(user);
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
Username = userName;
Input = new InputModel
{
Name = user.Name,
DOB = user.DOB,
PhoneNumber = phoneNumber
};
}
public async Task<IActionResult> OnGetAsync()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(
$"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
await LoadAsync(user);
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound(
$"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
if (!ModelState.IsValid)
{
await LoadAsync(user);
return Page();
}
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
if (Input.PhoneNumber != phoneNumber)
{
var setPhoneResult = await _userManager.SetPhoneNumberAsync(user,
Input.PhoneNumber);
if (!setPhoneResult.Succeeded)
{
var userId = await _userManager.GetUserIdAsync(user);
throw new InvalidOperationException(
$"Unexpected error occurred setting phone number for user with ID '{userId}'.");
}
}
if (Input.Name != user.Name)
{
user.Name = Input.Name;
}
if (Input.DOB != user.DOB)
{
user.DOB = Input.DOB;
}
await _userManager.UpdateAsync(user);
await _signInManager.RefreshSignInAsync(user);
StatusMessage = "Your profile has been updated";
return RedirectToPage();
}
}
öğesini Areas/Identity/Pages/Account/Manage/Index.cshtml aşağıdaki vurgulanmış işaretlemeyle güncelleştirin:
@page
@model IndexModel
@{
ViewData["Title"] = "Profile";
ViewData["ActivePage"] = ManageNavPages.Index;
}
<h4>@ViewData["Title"]</h4>
<partial name="_StatusMessage" model="Model.StatusMessage" />
<div class="row">
<div class="col-md-6">
<form id="profile-form" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Username"></label>
<input asp-for="Username" class="form-control" disabled />
</div>
<div class="form-group">
<label asp-for="Input.Name"></label>
<input asp-for="Input.Name" class="form-control" />
</div>
<div class="form-group">
<label asp-for="Input.DOB"></label>
<input asp-for="Input.DOB" class="form-control" />
</div>
<div class="form-group">
<label asp-for="Input.PhoneNumber"></label>
<input asp-for="Input.PhoneNumber" class="form-control" />
<span asp-validation-for="Input.PhoneNumber"
class="text-danger"></span>
</div>
<button id="update-profile-button" type="submit"
class="btn btn-primary">Save</button>
</form>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Account/Register.cshtml sayfasını güncelleştirme
InputModel öğesini Areas/Identity/Pages/Account/Register.cshtml.cs içindeki aşağıdaki vurgulanmış kodla güncelleyin.
[AllowAnonymous]
public class RegisterModel : PageModel
{
private readonly SignInManager<WebApp1User> _signInManager;
private readonly UserManager<WebApp1User> _userManager;
private readonly ILogger<RegisterModel> _logger;
private readonly IEmailSender _emailSender;
public RegisterModel(
UserManager<WebApp1User> userManager,
SignInManager<WebApp1User> signInManager,
ILogger<RegisterModel> logger,
IEmailSender emailSender)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
_emailSender = emailSender;
}
[BindProperty]
public InputModel Input { get; set; }
public string ReturnUrl { get; set; }
public IList<AuthenticationScheme> ExternalLogins { get; set; }
public class InputModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Full name")]
public string Name { get; set; }
[Required]
[Display(Name = "Birth Date")]
[DataType(DataType.Date)]
public DateTime DOB { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
public async Task OnGetAsync(string returnUrl = null)
{
ReturnUrl = returnUrl;
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
}
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
if (ModelState.IsValid)
{
var user = new WebApp1User {
Name = Input.Name,
DOB = Input.DOB,
UserName = Input.Email,
Email = Input.Email
};
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email,
"Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
if (_userManager.Options.SignIn.RequireConfirmedAccount)
{
return RedirectToPage("RegisterConfirmation", new { email = Input.Email });
}
else
{
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
}
öğesini Areas/Identity/Pages/Account/Register.cshtml aşağıdaki vurgulanmış işaretlemeyle güncelleştirin:
@page
@model RegisterModel
@{
ViewData["Title"] = "Register";
}
<h1>@ViewData["Title"]</h1>
<div class="row">
<div class="col-md-4">
<form asp-route-returnUrl="@Model.ReturnUrl" method="post">
<h4>Create a new account.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Name"></label>
<input asp-for="Input.Name" class="form-control" />
<span asp-validation-for="Input.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.DOB"></label>
<input asp-for="Input.DOB" class="form-control" />
<span asp-validation-for="Input.DOB" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Password"></label>
<input asp-for="Input.Password" class="form-control" />
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.ConfirmPassword"></label>
<input asp-for="Input.ConfirmPassword" class="form-control" />
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
</div>
<div class="col-md-6 col-md-offset-2">
<section>
<h4>Use another service to register.</h4>
<hr />
@{
if ((Model.ExternalLogins?.Count ?? 0) == 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 id="external-account" asp-page="./ExternalLogin"
asp-route-returnUrl="@Model.ReturnUrl" method="post"
class="form-horizontal">
<div>
<p>
@foreach (var provider in Model.ExternalLogins)
{
<button type="submit" class="btn btn-primary" name="provider"
value="@provider.Name"
title="Log in using your @provider.DisplayName account">
@provider.DisplayName</button>
}
</p>
</div>
</form>
}
}
</section>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Projeyi oluşturun.
Özel kullanıcı verileri için geçiş ekleme
Visual Studio Paket Yöneticisi Konsolu'nda:
Add-Migration CustomUserData
Update-Database
Özel kullanıcı verilerini oluşturmayı, görüntülemeyi, indirmeyi, silmeyi test edin
Uygulamayı test edin:
- Yeni bir kullanıcı kaydedin.
- Sayfadaki özel kullanıcı verilerini
/Identity/Account/Managegörüntüleyin. - Kullanıcıların kişisel verilerini sayfadan
/Identity/Account/Manage/PersonalDataindirin ve görüntüleyin.
Identity üzerine IUserClaimsPrincipalFactory<ApplicationUser> kullanarak talep ekleyin
Note
Bu bölüm önceki eğitimin bir uzantısı değildir. Öğretici kullanılarak oluşturulan uygulamaya aşağıdaki adımları uygulamak için bu GitHub sorununa bakın.
arabirimi kullanılarak ASP.NET Core'a IdentityIUserClaimsPrincipalFactory<T> ek talepler eklenebilir. Bu sınıf, Startup.ConfigureServices yönteminde uygulamaya eklenebilir. Sınıfın özel uygulamasını aşağıdaki gibi ekleyin:
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>,
AdditionalUserClaimsPrincipalFactory>();
Tanıtım kodu sınıfını ApplicationUser kullanır. Bu sınıf, ek talebi eklemek için kullanılan bir IsAdmin özellik ekler.
public class ApplicationUser : IdentityUser
{
public bool IsAdmin { get; set; }
}
AdditionalUserClaimsPrincipalFactory arabirimini UserClaimsPrincipalFactory uygular. Yeni bir rol talebi ClaimsPrincipal öğesine eklenir.
public class AdditionalUserClaimsPrincipalFactory
: UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>
{
public AdditionalUserClaimsPrincipalFactory(
UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole> roleManager,
IOptions<IdentityOptions> optionsAccessor)
: base(userManager, roleManager, optionsAccessor)
{}
public async override Task<ClaimsPrincipal> CreateAsync(ApplicationUser user)
{
var principal = await base.CreateAsync(user);
var identity = (ClaimsIdentity)principal.Identity;
var claims = new List<Claim>();
if (user.IsAdmin)
{
claims.Add(new Claim(JwtClaimTypes.Role, "admin"));
}
else
{
claims.Add(new Claim(JwtClaimTypes.Role, "user"));
}
identity.AddClaims(claims);
return principal;
}
}
Daha sonra ek talep uygulamada kullanılabilir. Bir Razor Sayfada, IAuthorizationService örnek talep değerine erişmek için kullanılabilir.
@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService
@if ((await AuthorizationService.AuthorizeAsync(User, "IsAdmin")).Succeeded)
{
<ul class="mr-auto navbar-nav">
<li class="nav-item">
<a class="nav-link" asp-controller="Admin" asp-action="Index">ADMIN</a>
</li>
</ul>
}
Razor Web uygulaması oluşturma
- Visual Studio Dosya menüsünden, Yeni>Proje'yi seçin. İndirme örnek kodunun ad alanıyla eşleşmesini istiyorsanız projeyi WebApp1 olarak adlandırın.
- ASP.NET Çekirdek Web Uygulaması>Tamam'ı seçin
- Açılan listeden ASP.NET Core 2.2'yi seçin
- Web Uygulaması>Tamam'ı seçin
- Projeyi derleyin ve çalıştırın.
Scaffolder'ı Identity çalıştır
- Çözüm Gezgini, Projeye Yeni İskeleli Öğe>>sağ tıklayın.
- İskelet Ekle iletişim kutusunun sol bölmesinden, Identity'yi seçin>.
-
Ekle Identity iletişim kutusunda aşağıdaki seçenekler:
- Var olan düzen dosyasını seçin
~/Pages/Shared/_Layout.cshtml - Geçersiz kılmak için aşağıdaki dosyaları seçin:
- Account/Register
- Account/Manage/Index
- + Yeni bir Veri bağlam sınıfı oluşturmak için düğmesini seçin. Türü kabul edin (Projenin adı WebApp1 ise WebApp1.Models.WebApp1Context).
- + Yeni bir Kullanıcı sınıfı oluşturmak için düğmesini seçin. Proje WebApp1 olarak adlandırılmışsa, türü WebApp1User olarak kabul edin ve >.
- Var olan düzen dosyasını seçin
- Add (Ekle) seçeneğini belirleyin.
Aşağıdaki adımları gerçekleştirmek için Geçişler, UseAuthentication ve düzen yönergelerini izleyin:
- Geçiş oluşturun ve veritabanını güncelleştirin.
-
UseAuthentication'yiStartup.Configure'ye ekle. - Düzen dosyasına
<partial name="_LoginPartial" />ekleyin. - Uygulamayı test edin:
- Kullanıcı kaydetme
- Yeni kullanıcı adını seçin ( Oturum Kapatma bağlantısının yanında). Kullanıcı adını ve diğer bağlantıları göstermek için pencereyi genişletmeniz veya gezinti çubuğu simgesini seçmeniz gerekebilir.
- Kişisel Veriler sekmesini seçin.
-
İndir düğmesini seçin ve dosyayı incelediniz
PersonalData.json. - Oturum açmış kullanıcıyı silen Sil düğmesini test edin.
Db'ye Identity özel kullanıcı verileri ekleme
IdentityUser Türetilmiş sınıfı özel özelliklerle güncelleştirin. Projeyi WebApp1 olarak adlandırdıysanız, dosya olarak adlandırılır Areas/Identity/Data/WebApp1User.cs. Dosyayı aşağıdaki kodla güncelleştirin:
using Microsoft.AspNetCore.Identity;
using System;
namespace WebApp1.Areas.Identity.Data
{
public class WebApp1User : IdentityUser
{
[PersonalData]
public string Name { get; set; }
[PersonalData]
public DateTime DOB { get; set; }
}
}
PersonalData özniteliğine sahip özellikler şunlardır:
- Silindiğinde
Areas/Identity/Pages/Account/Manage/DeletePersonalData.cshtmlRazor SayfaUserManager.Deleteçalıştırır. - İndirilen verilere
Areas/Identity/Pages/Account/Manage/DownloadPersonalData.cshtmlRazor Sayfa tarafından eklenmiştir.
Account/Manage/Index.cshtml sayfasını güncelleştirme
InputModel öğesini Areas/Identity/Pages/Account/Manage/Index.cshtml.cs içindeki aşağıdaki vurgulanmış kodla güncelleyin.
public partial class IndexModel : PageModel
{
private readonly UserManager<WebApp1User> _userManager;
private readonly SignInManager<WebApp1User> _signInManager;
private readonly IEmailSender _emailSender;
public IndexModel(
UserManager<WebApp1User> userManager,
SignInManager<WebApp1User> signInManager,
IEmailSender emailSender)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
}
public string Username { get; set; }
public bool IsEmailConfirmed { get; set; }
[TempData]
public string StatusMessage { get; set; }
[BindProperty]
public InputModel Input { get; set; }
public class InputModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Full name")]
public string Name { get; set; }
[Required]
[Display(Name = "Birth Date")]
[DataType(DataType.Date)]
public DateTime DOB { get; set; }
[Required]
[EmailAddress]
public string Email { get; set; }
[Phone]
[Display(Name = "Phone number")]
public string PhoneNumber { get; set; }
}
public async Task<IActionResult> OnGetAsync()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
var userName = await _userManager.GetUserNameAsync(user);
var email = await _userManager.GetEmailAsync(user);
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
Username = userName;
Input = new InputModel
{
Name = user.Name,
DOB = user.DOB,
Email = email,
PhoneNumber = phoneNumber
};
IsEmailConfirmed = await _userManager.IsEmailConfirmedAsync(user);
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
var email = await _userManager.GetEmailAsync(user);
if (Input.Email != email)
{
var setEmailResult = await _userManager.SetEmailAsync(user, Input.Email);
if (!setEmailResult.Succeeded)
{
var userId = await _userManager.GetUserIdAsync(user);
throw new InvalidOperationException($"Unexpected error occurred setting email for user with ID '{userId}'.");
}
}
if (Input.Name != user.Name)
{
user.Name = Input.Name;
}
if (Input.DOB != user.DOB)
{
user.DOB = Input.DOB;
}
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
if (Input.PhoneNumber != phoneNumber)
{
var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
if (!setPhoneResult.Succeeded)
{
var userId = await _userManager.GetUserIdAsync(user);
throw new InvalidOperationException($"Unexpected error occurred setting phone number for user with ID '{userId}'.");
}
}
await _userManager.UpdateAsync(user);
await _signInManager.RefreshSignInAsync(user);
StatusMessage = "Your profile has been updated";
return RedirectToPage();
}
public async Task<IActionResult> OnPostSendVerificationEmailAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
var userId = await _userManager.GetUserIdAsync(user);
var email = await _userManager.GetEmailAsync(user);
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { userId = userId, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(
email,
"Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
StatusMessage = "Verification email sent. Please check your email.";
return RedirectToPage();
}
}
öğesini Areas/Identity/Pages/Account/Manage/Index.cshtml aşağıdaki vurgulanmış işaretlemeyle güncelleştirin:
@page
@model IndexModel
@{
ViewData["Title"] = "Profile";
ViewData["ActivePage"] = ManageNavPages.Index;
}
<h4>@ViewData["Title"]</h4>
<partial name="_StatusMessage" for="StatusMessage" />
<div class="row">
<div class="col-md-6">
<form id="profile-form" method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Username"></label>
<input asp-for="Username" class="form-control" disabled />
</div>
<div class="form-group">
<label asp-for="Input.Email"></label>
@if (Model.IsEmailConfirmed)
{
<div class="input-group">
<input asp-for="Input.Email" class="form-control" />
<span class="input-group-addon" aria-hidden="true"><span class="glyphicon glyphicon-ok text-success"></span></span>
</div>
}
else
{
<input asp-for="Input.Email" class="form-control" />
<button id="email-verification" type="submit" asp-page-handler="SendVerificationEmail" class="btn btn-link">Send verification email</button>
}
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Name"></label>
<input asp-for="Input.Name" class="form-control" />
</div>
<div class="form-group">
<label asp-for="Input.DOB"></label>
<input asp-for="Input.DOB" class="form-control" />
</div>
<div class="form-group">
<label asp-for="Input.PhoneNumber"></label>
<input asp-for="Input.PhoneNumber" class="form-control" />
<span asp-validation-for="Input.PhoneNumber" class="text-danger"></span>
</div>
<button id="update-profile-button" type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Account/Register.cshtml sayfasını güncelleştirme
InputModel öğesini Areas/Identity/Pages/Account/Register.cshtml.cs içindeki aşağıdaki vurgulanmış kodla güncelleyin.
[AllowAnonymous]
public class RegisterModel : PageModel
{
private readonly SignInManager<WebApp1User> _signInManager;
private readonly UserManager<WebApp1User> _userManager;
private readonly ILogger<RegisterModel> _logger;
private readonly IEmailSender _emailSender;
public RegisterModel(
UserManager<WebApp1User> userManager,
SignInManager<WebApp1User> signInManager,
ILogger<RegisterModel> logger,
IEmailSender emailSender)
{
_userManager = userManager;
_signInManager = signInManager;
_logger = logger;
_emailSender = emailSender;
}
[BindProperty]
public InputModel Input { get; set; }
public string ReturnUrl { get; set; }
public class InputModel
{
[Required]
[DataType(DataType.Text)]
[Display(Name = "Full name")]
public string Name { get; set; }
[Required]
[Display(Name = "Birth Date")]
[DataType(DataType.Date)]
public DateTime DOB { get; set; }
[Required]
[EmailAddress]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
public void OnGet(string returnUrl = null)
{
ReturnUrl = returnUrl;
}
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
var user = new WebApp1User {
Name = Input.Name,
DOB = Input.DOB,
UserName = Input.Email,
Email = Input.Email
};
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
}
öğesini Areas/Identity/Pages/Account/Register.cshtml aşağıdaki vurgulanmış işaretlemeyle güncelleştirin:
@page
@model RegisterModel
@{
ViewData["Title"] = "Register";
}
<h1>@ViewData["Title"]</h1>
<div class="row">
<div class="col-md-4">
<form asp-route-returnUrl="@Model.ReturnUrl" method="post">
<h4>Create a new account.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Input.Name"></label>
<input asp-for="Input.Name" class="form-control" />
<span asp-validation-for="Input.Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.DOB"></label>
<input asp-for="Input.DOB" class="form-control" />
<span asp-validation-for="Input.DOB" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Email"></label>
<input asp-for="Input.Email" class="form-control" />
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.Password"></label>
<input asp-for="Input.Password" class="form-control" />
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Input.ConfirmPassword"></label>
<input asp-for="Input.ConfirmPassword" class="form-control" />
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
</div>
</div>
@section Scripts {
<partial name="_ValidationScriptsPartial" />
}
Projeyi oluşturun.
Özel kullanıcı verileri için geçiş ekleme
Visual Studio Paket Yöneticisi Konsolu'nda:
Add-Migration CustomUserData
Update-Database
Özel kullanıcı verilerini oluşturmayı, görüntülemeyi, indirmeyi, silmeyi test edin
Uygulamayı test edin:
- Yeni bir kullanıcı kaydedin.
- Sayfadaki özel kullanıcı verilerini
/Identity/Account/Managegörüntüleyin. - Kullanıcıların kişisel verilerini sayfadan
/Identity/Account/Manage/PersonalDataindirin ve görüntüleyin.
ASP.NET Core