.NET Core 2.1 + Identity as UIアプリケーションの「登録」オプションをキャンセルしたい。
もちろん、ページからボタンを単純に削除することができます、質問は-それは安全ですか?
そうでない場合、他のオプションは何ですか?足場を使用して登録コードを生成し、そこで無効にする必要がありますか?
(SetPasswordなども同様です)
ありがとう
残念ながら、他の2つの答えは間違っています-質問は実際には、デフォルトのUIを提供するためにRazorページを使用する新しいAddDefaultIdentity()拡張機能を参照しています。これに対処する答えは、not質問で要求されたレジスタ機能を削除します。
AddDefaultIdentityはAddIdentityと同様の方法で機能しますが、新しいIDカミソリビュー(現在28個)へのアクセスをアプリに許可するAddDefaultUIへの呼び出しも含まれています。これらは新しいカミソリクラスライブラリにあります。これがAddDefaultIdentityとAddIdentityの唯一の違いではないことに注意してください(後述)。
デフォルトのビューを変更するには、プロジェクト内のビューをオーバーライド(「足場」)する必要があります。その後、それらを修正できます。ビューをオーバーライドしない場合、またはビューをオーバーライドしてからcshtmlファイルを削除した場合、デフォルトのUIバージョンに戻るだけです!たとえば、リンクを削除しても登録すると、ユーザーはURLを推測した場合でもデフォルトの登録ビューに移動できます。
いくつかのデフォルトビューを保持し、他のビューを修正または削除する場合は、次のようにビューをオーバーライドできます( from doc ):
オーバーライドしたビューの外観と機能を単に変更するか、「削除」するために404を返すか、他の場所にリダイレクトすることができます。このオーバーライドされたビューを削除すると、デフォルトのUIが表示されます!
すべてのビューをオーバーライドする場合、このアプローチはすぐに面倒になります。
別のオプションは、AddDefaultUIを呼び出さないIDを追加する古い方法に戻ることです。欠点は、すべてのビューを自分で追加する必要があることです。次のようにしてこれを行うことができます( このドキュメントから -上記のオプション1に適用される、すべてのビューのオーバーライドに関する最初の行を無視します):
//remove this: services.AddDefaultIdentity<IdentityUser>()
//use this instead to get the Identity basics without any default UI:
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
//this assumes you want to continue using razor views for your identity UI
//it specifies areas can be used with razor pages and then adds an
//authorize filter with a default policy for the folder /Account/Manage and
//the page /Account/Logout.cshtml (both of which live in Areas/Identity/Pages)
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddRazorPagesOptions(options =>
{
options.AllowAreas = true;
options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
});
//configures the application cookie to redirect on challenge, etc.
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = $"/Identity/Account/Login";
options.LogoutPath = $"/Identity/Account/Logout";
options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
});
//configures an email sender for e.g. password resets
services.AddSingleton<IEmailSender, EmailSender>();
上記のように、AddDefaultIdentityとAddIdentityには別の違いがあるため、この2番目のアプローチにも問題がないと100%確信しているわけではないことに注意してください。たとえば、後者はRoleManagerサービスを追加しますが、前者は追加しません。また、これらのアプローチの両方が今後も同様にサポートおよび維持されるかどうかは不明です。
上記のオプションが何をしているのか疑問がある場合(そして、数時間殺す場合)、 AddDefaultIdentityのソース ( AddIdentityCookies および- AddIdentityCore )古いものと比較 AddIdentity 。
現時点での最良の選択肢は、おそらく前の2つを次のように組み合わせることです。
これで、必要なビューのみが作成され、デフォルトの実装に基づいているため、これらのビューのほとんどの作業が完了します。
ASP.NET Webページの場合、これは、ASP.Net razor Web Pagesを含めるための以前の回答のアドオンです。私は、誰かがそれらを必要とし、互いに混同しないようにこれらを分離しました。 Webページには、Webフォームのようにコードビハインドが含まれているため、異なります。
まず、ページ> _LoginPartial.cshtmlを編集します
行<li><a asp-page="/Account/Register">Register</a></li>
を削除
[ページの編集]> [アカウント]> [Login.cshtml]。以下を削除します。
<div class="form-group">
<p>
<a asp-page="./ForgotPassword">Forgot your password?</a>
</p>
<p>
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
</p>
</div>
以下も削除します:
<div class="col-md-6 col-md-offset-2">
<section>
<h4>Use another service to log in.</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 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-default" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
}
</p>
</div>
</form>
}
}
</section>
</div>
Login.cshtml.csの背後にあるコードを編集します
削除する:
public IList<AuthenticationScheme> ExternalLogins { get; set; }
また削除:
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
ページの編集>アカウント>管理> _ManageNav.cshtml
削除する:
@if (hasExternalLogins)
{
<li class="@ManageNavPages.ExternalLoginsNavClass(ViewContext)"><a asp-page="./ExternalLogins">External logins</a></li>
}
次に、ページ>アカウントディレクトリから次のファイルを削除します。
Pages> Account> Manageディレクトリから次のファイルを削除します。
Model-View-Controller Webアプリケーションについて話していると思います。ボタンを削除するだけでなく、そのようなビューを削除することも安全ではないと言えます。
また、登録ユーザーを作成するサードパーティのログインを削除することも想定しています。
私は次のことをします:
アカウントコントローラーで次を削除します
[HttpGet]
[AllowAnonymous]
public IActionResult Register(string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme);
await _emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl);
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation("User created a new account with password.");
return RedirectToLocal(returnUrl);
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
また、アカウントコントローラーで、さらに以下を削除します。
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public IActionResult ExternalLogin(string provider, string returnUrl = null)
{
// Request a redirect to the external login provider.
var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider);
}
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
if (remoteError != null)
{
ErrorMessage = $"Error from external provider: {remoteError}";
return RedirectToAction(nameof(Login));
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction(nameof(Login));
}
// Sign in the user with this external login provider if the user already has a login.
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
if (result.Succeeded)
{
_logger.LogInformation("User logged in with {Name} provider.", info.LoginProvider);
return RedirectToLocal(returnUrl);
}
if (result.IsLockedOut)
{
return RedirectToAction(nameof(Lockout));
}
else
{
// If the user does not have an account, then ask the user to create an account.
ViewData["ReturnUrl"] = returnUrl;
ViewData["LoginProvider"] = info.LoginProvider;
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
return View("ExternalLogin", new ExternalLoginViewModel { Email = email });
}
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginViewModel model, string returnUrl = null)
{
if (ModelState.IsValid)
{
// Get the information about the user from the external login provider
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
throw new ApplicationException("Error loading external login information during confirmation.");
}
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user);
if (result.Succeeded)
{
result = await _userManager.AddLoginAsync(user, info);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider);
return RedirectToLocal(returnUrl);
}
}
AddErrors(result);
}
ViewData["ReturnUrl"] = returnUrl;
return View(nameof(ExternalLogin), model);
}
また削除する
[HttpGet]
[AllowAnonymous]
public IActionResult ForgotPassword()
{
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
if (ModelState.IsValid)
{
var user = await _userManager.FindByEmailAsync(model.Email);
if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
{
// Don't reveal that the user does not exist or is not confirmed
return RedirectToAction(nameof(ForgotPasswordConfirmation));
}
// For more information on how to enable account confirmation and password reset please
// visit https://go.Microsoft.com/fwlink/?LinkID=532713
var code = await _userManager.GeneratePasswordResetTokenAsync(user);
var callbackUrl = Url.ResetPasswordCallbackLink(user.Id, code, Request.Scheme);
await _emailSender.SendEmailAsync(model.Email, "Reset Password",
$"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>");
return RedirectToAction(nameof(ForgotPasswordConfirmation));
}
// If we got this far, something failed, redisplay form
return View(model);
}
[HttpGet]
[AllowAnonymous]
public IActionResult ForgotPasswordConfirmation()
{
return View();
}
[HttpGet]
[AllowAnonymous]
public IActionResult ResetPassword(string code = null)
{
if (code == null)
{
throw new ApplicationException("A code must be supplied for password reset.");
}
var model = new ResetPasswordViewModel { Code = code };
return View(model);
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _userManager.FindByEmailAsync(model.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToAction(nameof(ResetPasswordConfirmation));
}
var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password);
if (result.Succeeded)
{
return RedirectToAction(nameof(ResetPasswordConfirmation));
}
AddErrors(result);
return View();
}
[HttpGet]
[AllowAnonymous]
public IActionResult ResetPasswordConfirmation()
{
return View();
}
これで、[モデル]で次のファイルを削除できます。
ビューの下で私は削除します:
また、アカウントビューでLogin.cshtmlを編集し、次を削除します。
<div class="form-group">
<p>
<a asp-page="./ForgotPassword">Forgot your password?</a>
</p>
<p>
<a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
</p>
</div>
以下も削除します:
<div class="col-md-6 col-md-offset-2">
<section>
<h4>Use another service to log in.</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 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-default" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
}
</p>
</div>
</form>
}
}
</section>
</div>
共有ビューで_LoginPartial.cshtmlを開き、次を削除します。
<li><a asp-area="" asp-controller="Account" asp-action="Register">Register</a></li>
[ビューの管理] _ManageNav.cshtmlで、次を削除します。
@if (hasExternalLogins)
{
<li class="@ManageNavPages.ExternalLoginsNavClass(ViewContext)"><a asp-action="ExternalLogins">External logins</a></li>
}
URL yourapp.com/Account/Registerにアクセスしても、404ページが表示されます。
お役に立てれば。