Изменить маршрутизацию в ASP.NET Core Identity UI?

Я использую новый пакет Identity UI, доступный с момента выпуска ASP.NET Core 2.1. Используя недавно созданный проект MVC, вот несколько доступных URL-адресов страниц:

/Home/About
/Home/Contact
/Identity/Account/Login
/Identity/Account/Register

Как я могу настроить маршрутизацию для удаления /Identity/ часть из URL?

7 ответов

Решение

Похоже, это пока невозможно. Глядя на исходный код, становится ясно, что имя области жестко закодировано в IdentityDefaultUIConfigureOptions<TUser>:

private const string IdentityUIDefaultAreaName = "Identity";

Это используется в нескольких местах, в том числе при настройке Razor Pages. например:

options.Conventions.AuthorizeAreaFolder(IdentityUIDefaultAreaName, "/Account/Manage");

А также при настройке аутентификации Cookies. например:

options.LoginPath = $"/{IdentityUIDefaultAreaName}/Account/Login";

Стоит отметить, что IdentityDefaultUIConfigureOptions<TUser> сама защищена, поэтому возможности переопределения параметров не существует.

Я открыл выпуск Github, чтобы узнать, сможем ли мы получить отзывы от тех, кто участвует в самом проекте.


2018-06-12 Обновление

Хавьер Кальварро Нельсон (Javier Calvarro Nelson) из группы ASP.NET Core Identity поделился некоторыми ценными отзывами о проблеме Github, которую я поднял, и можно резюмировать следующим образом:

Основная причина, по которой интерфейс Identity находится в определенной области, состоит в том, чтобы минимизировать влияние на ваше приложение и обеспечить четкое разделение между кодом приложения и кодом Identity.

Хавьер рекомендует одну из следующих опций при желании настроить URL-адреса:

  • Используйте элемент scaffolding пользовательского интерфейса по умолчанию и сделайте все необходимые настройки самостоятельно.
  • Используйте правило перенаправления, которое указывает старые маршруты на новые маршруты.
  • Не используйте пользовательский интерфейс по умолчанию вообще.

Хотя это не поддерживается и не рекомендуется, Хавьер также указывает, что можно использовать пользовательские IPageApplicationModelConvention переопределить URL-адреса. Однако, если вы пропустили это, это не поддерживается и не рекомендуется.


2018-06-27 Обновление

Официальная документация была обновлена, чтобы лучше объяснить указанные изменения URL.

Самое простое, что можно сделать, это перетащить папку Pages из Areas/Identity в основной проект. Помните, что директива @page (в.cshtml) обеспечивает прямой доступ к представлениям для чего-либо в разделе "Страницы" (страница превращается в действие). Вы также можете переименовать папку "Учетная запись" на другое имя, если хотите изменить страницы по умолчанию / "Учетная запись" / "Логин" и т. д.

директива @page также может использоваться для указания пользовательского пути, например: @page "/Login"

чтобы получить доступ к странице входа в систему напрямую, перейдя в / Войти

В вашем startup.cs вы можете изменить:

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

с:

    services.AddMvc().AddRazorPagesOptions(o => o.Conventions.AddAreaFolderRouteModelConvention("Identity", "/Account/", model =>
    {
        foreach (var selector in model.Selectors)
        {
            var attributeRouteModel = selector.AttributeRouteModel;
            attributeRouteModel.Order = -1;
            attributeRouteModel.Template = attributeRouteModel.Template.Remove(0, "Identity".Length);
        }
    })
).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

Это будет маршрут:

/ Личность / Аккаунт / Войти в / Аккаунт / Войти

/ Личность / Аккаунт / Зарегистрироваться в / Аккаунт / Зарегистрироваться

так далее...

Для обработки ReturnUrl вы можете создать новое действие:

    [Route("Identity/Account/Login")]
    public IActionResult LoginRedirect(string ReturnUrl)
    {
        return Redirect("/Account/Login?ReturnUrl=" + ReturnUrl);
    }

Согласно ответу David Bouška , мне удалось избавиться от «Identity / Account» в маршруте страницы входа. Я работаю над приложением Asp.net 3.1 и использую скаффолд-страницы Identity.

Я изменил директиву @page на странице login.cshtml, как показано ниже, и изменил файл startup.cs, как показано ниже.

login.cshtml

      @page "/Login"

startup.cs

      services.ConfigureApplicationCookie(options =>
        {
            // httponly cookie
            options.Cookie.HttpOnly = true;
            options.Cookie.Name = "application.Identity";
            ***options.LoginPath = "/Login";*** // earlier it was options.LoginPath = "/Identity/Account/Login";
            options.AccessDeniedPath = "/Error/Index/403";
            options.ExpireTimeSpan = TimeSpan.FromMinutes(20);
            options.SlidingExpiration = true;
        });

Также обратите внимание, что если вы используете "/ Identity / Account / Login" в любом месте вашего приложения, вам может потребоваться их также изменить. Кроме того, если у вас такой же маршрут MVC, вам нужно быть более осторожным и обрабатывать его соответствующим образом.

Промежуточное программное обеспечение перезаписи URL может быть решением:

var options = new RewriteOptions()
        .AddRewrite(@"^Account/(.*)", "Identity/Account/$1", skipRemainingRules: true);
        app.UseRewriter(options);

Что касается .net core 3.1 и 2021 года (я знаю, что существует .net 5, виновный по обвинению), и хотя он обычно не удаляет «идентификационную» часть пути, вы можете сопоставить сгенерированные страницы бритвы одну за другой с желаемыми маршрутами:

в заголовке страницы по умолчанию только @page, так что измените его на желаемый маршрут @page "/login".

Обратите внимание, что если какой-либо маршрут mvc соответствует маршруту / логину, он будет использовать соответствующее действие контроллера. Если вы не хотите, чтобы ваш маршрут mvc переопределял маршрутизацию страниц бритвы, я бы предложил переместить endpoints.MapRazorPages(); в Configure метод Startup.cs прежде всего (или, по крайней мере, некоторые) маршруты mvc.

Что касается маршрутизации, то для стандартного веб-фреймворка с фиксированными URL-адресами аутентификации Django делает то же самое. Вот как настроить вид по своему вкусу, поэтому вместо удаления /Identity/ из маршрутов мы скажем Identity не включать их представления и предоставить маршрут для наших.

Идти к Startup.cs:

// USE METHOD WITH LESS DEFAULTS
//
// services.AddDefaultIdentity<IdentityUser>()
//    .AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentity<IdentityUser, IdentityRole>(options => options.Stores.MaxLengthForKeys = 128)
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();
//
// ADD A ROUTE BELOW THE DEFAULT ROUTE
//
routes.MapRoute(
            name: "identity",
            template: "Identity/{controller=Account}/{action=Register}/{id?}");

Теперь у нас есть все настройки, кроме представления, поэтому нам нужно проложить маршрут к нему так, как мы это обычно делаем в mvc. Сделайте аккаунт-контроллер. Измените индекс () на регистр (). Создайте папку в представлениях с именем Account. Добавить файл Register.cshtml, вот оригинальный HTML, настроить в соответствии с вашими потребностями:

<div class="container body-content">


<h2>Register</h2>

<div class="row">
    <div class="col-md-4">
        <form method="post" action="/Identity/Account/Register" novalidate="novalidate">
            <h4>Create a new account.</h4>
            <hr>
            <div class="text-danger validation-summary-valid" data-valmsg-summary="true"><ul><li style="display:none"></li>
</ul></div>
            <div class="form-group">
                <label for="Input_Email">Email</label>
                <input class="form-control" type="email" data-val="true" data-val-email="The Email field is not a valid e-mail address." data-val-required="The Email field is required." id="Input_Email" name="Input.Email" value="">
                <span class="text-danger field-validation-valid" data-valmsg-for="Input.Email" data-valmsg-replace="true"></span>
            </div>
            <div class="form-group">
                <label for="Input_Password">Password</label>
                <input class="form-control" type="password" data-val="true" data-val-length="The Password must be at least 6 and at max 100 characters long." data-val-length-max="100" data-val-length-min="6" data-val-required="The Password field is required." id="Input_Password" name="Input.Password">
                <span class="text-danger field-validation-valid" data-valmsg-for="Input.Password" data-valmsg-replace="true"></span>
            </div>
            <div class="form-group">
                <label for="Input_ConfirmPassword">Confirm password</label>
                <input class="form-control" type="password" data-val="true" data-val-equalto="The password and confirmation password do not match." data-val-equalto-other="*.Password" id="Input_ConfirmPassword" name="Input.ConfirmPassword">
                <span class="text-danger field-validation-valid" data-valmsg-for="Input.ConfirmPassword" data-valmsg-replace="true"></span>
            </div>
            <button type="submit" class="btn btn-default">Register</button>
        <input name="__RequestVerificationToken" type="hidden" value="CfDJ8IWbPHM_NTJDv_7HGewWzbbRveP09yQOznYdTWL2aN5X_4_eVbNE1w8D_qz7zegloVtdAhuVOJbJLQo0ja73FB3PgYycyGpn-DfX3fJqv4Cx8ns6Ygh6M7nMxV0eozO7hoDxUfPwrIJb2RcFtyzhPpMevZ4P0M8aVyBP55SP-5C4l23dCtDXXUOAY_YLwt67dw"></form>
    </div>
</div>


        <hr>
        <footer>
            <p>© 2018 - SqlServerApp</p>
        </footer>
    </div> 
Другие вопросы по тегам