我在ASP.NET Core 3.0(正式发行版)上具有Blazor服务器Web应用程序。我添加了软件包Microsoft.AspNetCore.Identity.UI
3.0.0和Microsoft.AspNetCore.Identity.EntityFrameworkCore
3.0.0
在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核心身份,请确保您在数据库的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>();