Я хочу отменить параметр «Зарегистрировать» в приложении .NET Core 2.1 + Identity as UI.
Я, конечно, могу просто удалить кнопку со страницы, вопрос - это безопасно?
Если нет, то какие у меня другие варианты? должен ли я использовать скаффолдинг для генерации кода регистрации, а затем отключить его там?
(то же самое касается SetPassword и т. д.)
Спасибо
Обновлено: похоже, что информация об этом была добавлена здесь: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/scaffold-identity?view=aspnetcore-3.1&tabs=visual-studio#disable-register-page
Да, точно ....
Если убрали функционал регистрации? Как люди будут регистрироваться ?? Или вы будете использовать аутентификацию по рекламе?
Я разрешаю администраторам регистрировать пользователей через другое приложение
Я предполагаю, что вы говорите о веб-приложении модель-представление-контроллер. Я могу сказать вам, что просто удалять кнопку или даже представления для них небезопасно.
Я также предполагаю, что вы хотите удалить сторонний логин, который также создаст зарегистрированного пользователя.
Я бы сделал следующее:
В вашем контроллере учетной записи удалите следующие
[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.
Надеюсь это поможет.
Благодарность ! Я использую бритвенные страницы с Identity as UI. Я могу использовать строительные леса для создания кода для Register.cs и т. д., Будет ли это применяться?
Я отредактирую свой пост. Что касается бритвенных страниц, вы все равно можете удалить части контроллера, а затем вы можете удалить фактические представления, поскольку они содержат код позади, на самом деле не большая разница, кроме кода позади, просто нужно убедиться, что вы удалите выделенный код для каждого редактирования, как на странице входа.
большое спасибо .. еще одна возможность, которую я рассмотрел, заключалась в том, чтобы создать шаблонную регистрацию и изменить код для немедленного перенаправления на страницу с ошибкой, что-то вроде: ModelState.AddModelError (string.Empty, "Invalid registration try."); return Page (); .. как вы думаете, это хороший подход?
Это будет работать, за исключением того, что все, что вы делаете, делает представление бесполезным, если вы решите добавить API в свое приложение, вам также придется это учитывать. Также вам все равно придется иметь дело с внешним входом и убедиться, что он неактивен. Безопасность вашего приложения имеет большое значение, лучше удалить то, что вам не нужно, а не создавать обходной путь.
Завтра утром я создам еще один пошаговый ответ, так как мне нужно выйти из офиса прямо сейчас.
Для веб-страниц ASP.NET это дополнение к ответу, ранее включавшее веб-страницы ASP.Net razor. Я разделил их так, как будто они кому-то нужны, а не путать друг с другом. Веб-страницы отличаются тем, что включают в себя программный код, как и веб-формы.
Сначала вы отредактируете страницы> _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:
Удалите следующие файлы из каталога Pages> Account> Manage:
если вы удалите register.cshtml, это не приведет к тому, что фреймворк будет предполагать, что леса не существует, и неявно использовать встроенный код по умолчанию?
Я проверил эту теорию перед публикацией. Сборка прошла, как ожидалось, и все функции удалены. Встроенный код по умолчанию не заменяет функции, удаленные из идентификатора.
хорошо, отлично, спасибо !, я сейчас отмечу это как решение, хотя я все еще могу оставить заглушки и перенаправить на страницу с ошибкой
Это неверный ответ! Удаление шаблонных представлений будет просто означать, что вы вернетесь к пользовательскому интерфейсу по умолчанию, если вы удалили ссылки, пользователям просто нужно ввести правильный URL-адрес, чтобы перейти к представлениям, например вашдомен / аккаунт / регистрация
Они больше не могут получить доступ к представлениям после удаления представлений. вы получите 404, так как вы должны попытаться перейти по прямому URL-адресу, который вам не предоставлен без ссылки. Но если бы эти страницы не были удалены, да, вы были бы правы.
К сожалению, два других ответа неверны - вопрос фактически относится к новому расширению AddDefaultIdentity (), которое использует страницы Razor для обслуживания пользовательского интерфейса по умолчанию. Ответ на этот вопрос будет: нет удалит функциональность регистра, как указано в вопросе.
AddDefaultIdentity работает аналогично AddIdentity, но также включает вызов AddDefaultUI, который дает вашему приложению доступ к новым представлениям бритвы Identity (в настоящее время их 28), они находятся в новой библиотеке классов бритвы. Обратите внимание, что это не единственное различие между AddDefaultIdentity и AddIdentity (см. Ниже).
Чтобы изменить представления по умолчанию, вам необходимо переопределить («скаффолд») представления в вашем проекте, и затем вы можете изменить их. Если вы не переопределите представления или если вы переопределите их, а затем удалите файлы cshtml, вы просто вернетесь к версиям пользовательского интерфейса по умолчанию! Даже если вы удалите ссылки, например, register, пользователь по-прежнему может перейти к просмотру реестра по умолчанию, если угадывает URL-адрес.
Если вы хотите сохранить одни представления по умолчанию и изменить или удалить другие, вы можете переопределить представления следующим образом (из этого документа):
Теперь вы можете либо просто изменить внешний вид и функциональность переопределенного представления, либо «удалить» его, вы можете вернуть 404 или перенаправить в другое место. Если вы удалите это переопределенное представление, пользовательский интерфейс по умолчанию вернется!
Этот подход может быстро стать беспорядочным, если вы хотите переопределить все представления.
Другой вариант - вернуться к старому способу добавления идентификатора, при котором не вызывается AddDefaultUI, недостатком является то, что вам нужно будет добавить все представления самостоятельно. Вы можете сделать это следующим образом (из этого документа - хотя игнорируйте первую строку о переопределении всех представлений, которая применяется к варианту 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>();
Обратите внимание, что я не уверен на 100%, что и этот второй подход без проблем, как упоминалось выше, есть и другие различия между AddDefaultIdentity и AddIdentity. Например, последний добавляет службу RoleManager, а первый - нет. Кроме того, мне неясно, будут ли поддерживаться и поддерживаться оба этих подхода одинаково в будущем.
Если вы сомневаетесь в том, что делают вышеуказанные параметры (и если у вас есть несколько часов, чтобы убить), вы можете посмотреть источник для AddDefaultIdentity (который также вызывает AddIdentityCookies и AddIdentityCore) по сравнению со старым AddIdentity.
Лучшим вариантом в настоящее время, вероятно, является объединение двух предыдущих следующим образом:
Теперь у вас есть только те представления, которые вам нужны, и они основаны на реализациях по умолчанию, что означает, что большая часть работы выполняется за вас для этих представлений.
такие ненужные шаги для чего-то 99% людей должны будут сделать, не зная, что эти парни думали с этим. это как вернуться к старой волшебной BS веб-форм.
У меня была аналогичная проблема, но я хотел отключить все страницы / Identity / Account и добавил следующий код в свою конфигурацию файла Startup.cs.
app.Use(async (context, next) =>
{
if (context.Request.Path.Value.ToLower().StartsWith("/identity/account"))
{
context.Response.StatusCode = 404; //Not found
return;
}
await next();
});
Для вашей проблемы вы можете просто отключить регистрационную форму, используя следующий код, который я не тестировал, но я думаю, что он будет работать.
app.Use(async (context, next) =>
{
if (context.Request.Path.Value.ToLower().StartsWith("/identity/account/register"))
{
context.Response.StatusCode = 404; //Not found
return;
}
await next();
});
Этот код проверяет путь запроса и, если он начинается с / identity / account / register, возвращает код состояния 404 Not Found.
Это официальный способ сделать это в документации.
Отключить регистрацию пользователя
Взято из документов:
Идентичность эшафота. Включите Account.Register, Account.Login и Account.RegisterConfirmation
dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
Обновите области / удостоверения / страницы / учетную запись / Register.cshtml.cs, чтобы пользователи не могли зарегистрируйтесь с этой конечной точки:
public class RegisterModel : PageModel
{
public IActionResult OnGet()
{
return RedirectToPage("Login");
}
public IActionResult OnPost()
{
return RedirectToPage("Login");
}
}
Обновите разделы / Identity / Pages / Account / Register.cshtml, чтобы они были согласованными с предыдущими изменениями:
@page
@model RegisterModel
@{
ViewData["Title"] = "Go to Login";
}
<h1>@ViewData["Title"]</h1>
<li class = "nav-item">
<a class = "nav-link text-dark" asp-area = "Identity" asp-page = "/Account/Login">Login</a>
</li>
Закомментируйте или удалите ссылку для регистрации из Области / Идентификация / Страницы / Учетная запись / Login.cshtml
Обновите страницу Areas / Identity / Pages / Account / RegisterConfirmation.
Удалите код подтверждения из PageModel:
[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
public IActionResult OnGet()
{
return Page();
}
}
ПРИМЕЧАНИЕ. Это также добавит в проект контекст базы данных идентификатора по умолчанию. Если у вас уже есть контекст db, обязательно удалите тот, который добавлен каркасом.