Blazor Server Web应用程序中的剃须刀页面:@attribute [Authorize]和/或 无效

问题描述 投票:0回答:1

我在ASP.NET Core 3.0(正式发行版)上具有Blazor服务器Web应用程序。我添加了软件包Microsoft.AspNetCore.Identity.UI 3.0.0和Microsoft.AspNetCore.Identity.EntityFrameworkCore 3.0.0

我在这里遵循指南https://docs.microsoft.com/en-us/aspnet/core/security/blazor/?view=aspnetcore-3.0&tabs=visual-studio#authorizeview-component

Startup.cs中,我有

public void ConfigureServices(IServiceCollection services)
{
     services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>().AddEntityFrameworkStores<ApplicationDbContext>();
    // ....
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ...
    app.UseAuthentication();
    app.UseAuthorization();
// ...
}

MainLayout.razor中,授权工作成功

@inherits LayoutComponentBase
@implements IDisposable

@inject Microsoft.AspNetCore.Components.NavigationManager NavigationManager
@inject IJSRuntime JSRuntime

@using Microsoft.JSInterop;
    <AuthorizeView>
        <Authorized>
            <div class="sidebar">
                <div class="top-row logo-container pl-4 navbar-dark bg-light text-body">
                    <button class="navbar-toggler" @onclick="@ToggleNavMenu">
                        <span class="navbar-toggler-icon"></span>
                    </button>
                    <span class="logo-image" />
                    <div class="@($"theme-settings-collapsed { ThemeSwitcherShown }")">
                        <a class="nav-item nav-link" @onclick="@ToggleThemeSwitcherPanel" href="javascript:void(0);">
                            <span class="oi oi-cog"></span>
                        </a>
                    </div>
                </div>
                <div class="@NavMenuCssClass">
                    <NavMenu />
                </div>
            </div>

            <div class="main">
                <div class="top-row bg-light text-body px-4" id="navbar">
                    <div class="logo">
                        <h5 class="caption">Foo</h5>
                    </div>
                    <div class="@($"theme-settings { ThemeSwitcherShown }")">
                        <a class="nav-item nav-link" @onclick="@ToggleThemeSwitcherPanel" href="javascript:void(0);">
                            <span class="oi oi-cog"></span>
                        </a>
                    </div>
                </div>
                <ThemeSwitcher @bind-Shown="@ThemeSwitcherShown"></ThemeSwitcher>
                <div class="content px-4">
                    @Body
                </div>
            </div>

            </Authorized>
    </AuthorizeView>



                    @code {
                        bool collapseNavMenu = true;

                        string NavMenuCssClass => collapseNavMenu ? "collapse" : null;

                        void ToggleNavMenu()
                        {
                            collapseNavMenu = !collapseNavMenu;
                            ThemeSwitcherShown = false;
                        }

                        bool themeSwitcherShown = false;

                        bool ThemeSwitcherShown
                        {
                            get => themeSwitcherShown;
                            set
                            {
                                themeSwitcherShown = value;
                                InvokeAsync(StateHasChanged);
                            }
                        }

                        void ToggleThemeSwitcherPanel()
                        {
                            ThemeSwitcherShown = !ThemeSwitcherShown;
                            if (ThemeSwitcherShown)
                            {
                                collapseNavMenu = true;
                            }
                        }
                        string UriFragment { get; set; } = "";

                        void OnLocationChanged(object sender, LocationChangedEventArgs args)
                        {
                            JSRuntime.InvokeAsync<string>("ScrollToTarget", NavigationManager.ToAbsoluteUri(args.Location).Fragment);
                            if (!collapseNavMenu)
                            {
                                collapseNavMenu = true;
                                InvokeAsync(StateHasChanged);
                            }
                        }

                        protected override void OnInitialized()
                        {
                            base.OnInitialized();
                            NavigationManager.LocationChanged += OnLocationChanged;
                        }

                        protected override Task OnAfterRenderAsync(bool firstRender)
                        {
                            if (firstRender)
                            {
                                JSRuntime.InvokeAsync<string>("ScrollToTarget");
                            }
                            return base.OnAfterRenderAsync(firstRender);
                        }

                        void IDisposable.Dispose()
                        {
                            NavigationManager.LocationChanged -= OnLocationChanged;
                        }
                    }

首次尝试(使用@attribute [Authorize]

我有Foo.razor

@page "/foos"
@attribute [Authorize]
@*@attribute [Authorize(Roles = "admin, superuser")]*@
@attribute [Authorize(Roles = "ADMIN")]
@*@attribute [Authorize(Policy = "content-editor")]*@


@using awesomeProject.Models
@inject awesomeProject.Controllers.FoosController Controller
@inject IAuthorizationService AuthorizationService

<h1>List of foos</h1>

@if (FooList == null)
{
    <p>
        <em>Loading...</em>
    </p>
}
else
{ 
            <DxDataGrid Data="@FooList" PageSize="20" ShowFilterRow="true"
                        RowRemoving="@((dataItem) => OnRowRemoving(dataItem))"
                        RowInserting="@((newValues) => OnRowInserting(newValues))"
                        RowUpdating="@((updatingDataItem, newValues) => OnRowUpdating(updatingDataItem, newValues))">
                <DxDataGridCommandColumn Width="150px"></DxDataGridCommandColumn>
                <DxDataGridColumn Field="@nameof(Foo.Field1)" Caption="@("Field1")" TextAlignment="@DataGridTextAlign.Left"></DxDataGridColumn>
                <DxDataGridColumn Field="@nameof(Foo.Field2)" Caption="@("Field2")"></DxDataGridColumn>
                <DxDataGridColumn Field="@nameof(Foo.Field3)" Caption="@("Field3")" TextAlignment="@DataGridTextAlign.Left"></DxDataGridColumn>
                <DxDataGridColumn Field="@nameof(Foo.Field4)" Caption="@("Field4")" TextAlignment="@DataGridTextAlign.Left"></DxDataGridColumn>
                <DxDataGridColumn Field="@nameof(Foo.Field5)" Caption="@("Field5")" TextAlignment="@DataGridTextAlign.Left"></DxDataGridColumn>
                <DxDataGridColumn Field="@nameof(Foo.Field6)" Caption="@("Field6")" TextAlignment="@DataGridTextAlign.Left">
                    <EditTemplate Context="context2">
                        <DxComboBox Data="@(new List<string>() { "Yes", "No" })"
                                    SelectedItem="@(((bool)((CellEditContext)context2).CellValue) ? "Yes" : "No" )"
                                    SelectedItemChanged="@(newCellValue => ((CellEditContext)context2).OnChanged(newCellValue == "Yes"))">
                        </DxComboBox>
                    </EditTemplate>
                </DxDataGridColumn>
                <DxDataGridColumn Field="@nameof(Foo.Id)" Caption="@("Id")" TextAlignment="@DataGridTextAlign.Left" Visible="false"></DxDataGridColumn>
            </DxDataGrid>


}

@code {
    IEnumerable<Foo> FooList;

    protected override async Task OnInitializedAsync()
    {
        FooList = await Controller.GetAccountAsync();
    }

    async void OnRowRemoving(Foo dataItem)
    {
        FooList = await Controller.Delete(dataItem);
        await InvokeAsync(StateHasChanged);
    }

    async void OnRowInserting(Dictionary<string, object> newValue)
    {
        FooList = await Controller.Insert(newValue);
        await InvokeAsync(StateHasChanged);
    }

    async void OnRowUpdating(Foo dataItem, Dictionary<string, object> newValue)
    {
        FooList = await Controller.Update(dataItem, newValue);
        await InvokeAsync(StateHasChanged);
    }
}

((1)清除Web浏览器中的所有内容。

((2)转到https://localhost:44333/foos

((3)我看到“未授权”

((4)然后我通过https://localhost:44333/Identity/Account/Login登录(通过用户帐户具有角色ADMIN)。

((5)我进入https://localhost:44333/foos

((6)我仍然看到“未授权”]

第二次尝试使用<AuthorizeView><Authorized>

@page "/foos"

@using awesomeProject.Models
@inject awesomeProject.Controllers.FoosController Controller
@inject IAuthorizationService AuthorizationService

<h1>List of foos</h1>

@if (FooList == null)
{
    <p>
        <em>Loading...</em>
    </p>
}
else
{ 
    <AuthorizeView>
        <Authorized>

            <DxDataGrid Data="@FooList" PageSize="20" ShowFilterRow="true"
                        RowRemoving="@((dataItem) => OnRowRemoving(dataItem))"
                        RowInserting="@((newValues) => OnRowInserting(newValues))"
                        RowUpdating="@((updatingDataItem, newValues) => OnRowUpdating(updatingDataItem, newValues))">
                <DxDataGridCommandColumn Width="150px"></DxDataGridCommandColumn>
                <DxDataGridColumn Field="@nameof(Foo.Field1)" Caption="@("Field1")" TextAlignment="@DataGridTextAlign.Left"></DxDataGridColumn>
                <DxDataGridColumn Field="@nameof(Foo.Field2)" Caption="@("Field2")"></DxDataGridColumn>
                <DxDataGridColumn Field="@nameof(Foo.Field3)" Caption="@("Field3")" TextAlignment="@DataGridTextAlign.Left"></DxDataGridColumn>
                <DxDataGridColumn Field="@nameof(Foo.Field4)" Caption="@("Field4")" TextAlignment="@DataGridTextAlign.Left"></DxDataGridColumn>
                <DxDataGridColumn Field="@nameof(Foo.Field5)" Caption="@("Field5")" TextAlignment="@DataGridTextAlign.Left"></DxDataGridColumn>
                <DxDataGridColumn Field="@nameof(Foo.Field6)" Caption="@("Field6")" TextAlignment="@DataGridTextAlign.Left">
                    <EditTemplate Context="context2">
                        <DxComboBox Data="@(new List<string>() { "Yes", "No" })"
                                    SelectedItem="@(((bool)((CellEditContext)context2).CellValue) ? "Yes" : "No" )"
                                    SelectedItemChanged="@(newCellValue => ((CellEditContext)context2).OnChanged(newCellValue == "Yes"))">
                        </DxComboBox>
                    </EditTemplate>
                </DxDataGridColumn>
                <DxDataGridColumn Field="@nameof(Foo.Id)" Caption="@("Id")" TextAlignment="@DataGridTextAlign.Left" Visible="false"></DxDataGridColumn>
            </DxDataGrid>

        </Authorized>
  </AuthorizeView>   

}

@code {
    IEnumerable<Foo> FooList;

    protected override async Task OnInitializedAsync()
    {
        FooList = await Controller.GetAccountAsync();
    }

    async void OnRowRemoving(Foo dataItem)
    {
        FooList = await Controller.Delete(dataItem);
        await InvokeAsync(StateHasChanged);
    }

    async void OnRowInserting(Dictionary<string, object> newValue)
    {
        FooList = await Controller.Insert(newValue);
        await InvokeAsync(StateHasChanged);
    }

    async void OnRowUpdating(Foo dataItem, Dictionary<string, object> newValue)
    {
        FooList = await Controller.Update(dataItem, newValue);
        await InvokeAsync(StateHasChanged);
    }
}

((1)清除Web浏览器中的所有内容。

((2)转到https://localhost:44333/foos

((3)我看到“未授权”

((4)然后我通过https://localhost:44333/Identity/Account/Login登录(通过用户帐户具有角色ADMIN)。

((5)我进入https://localhost:44333/foos

((6)我仍然看到“未授权”]

我也尝试将<AuthorizeView>更改为<AuthorizeView Roles="ADMIN">,但相同。

这是错误还是其他错误?如何解决?

asp.net-core blazor asp.net-core-identity blazor-server-side asp.net-core-3.0
1个回答
0
投票

如果使用asp.net核心身份,请确保您在数据库的ADMIN表中具有正确的角色AspNetRoles,并且在数据库的AspNetUserRoles表中具有正确的用户角色关系。

我按照本教程进行操作,并通过单击此链接从用户创建角色,并且在重新启动站点时效果很好。https://stackoverflow.com/a/42481990/10158551

记住要由DI使用:

private readonly RoleManager<IdentityRole> _roleManager;
public LoginModel(RoleManager<IdentityRole> roleManager)
{
  _roleManager = roleManager
}

//In handler
bool x = await _roleManager.RoleExistsAsync("ADMIN");
if (!x)
{
    // first we create Admin role    
    var role = new IdentityRole();
    role.Name = "ADMIN";
    await _roleManager.CreateAsync(role);

    //assign role to the user
    var user = await _userManager.FindByNameAsync(Input.Email);
    var result1 = await _userManager.AddToRoleAsync(user, "ADMIN");

}

此外,您还需要为身份注册角色,例如

services.AddDefaultIdentity<IdentityUser>()
            .AddRoles<IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>();
© www.soinside.com 2019 - 2024. All rights reserved.