如何在ASP.NET Core 2.1中使用角色?

19

我使用以下内容创建了一个测试项目:

dotnet new razor --auth Individual --output Test

这将创建一个包含以下内容的 Startup.cs 文件:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlite(
            Configuration.GetConnectionString("DefaultConnection")));

    services.AddDefaultIdentity<IdentityUser>()
        .AddEntityFrameworkStores<ApplicationDbContext>();

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

我想种植一些用户和角色。用户和角色都将使用相同的存储(SQLite)。我正在使用一个名为Program的静态类进行播种。

我可以播种用户,但是无法播种角色,因为上述代码似乎没有注入RoleManager

在ASP.NET Core 2.0中,使用以下内容:

services.AddIdentity<IdentityUser, IdentityRole>()

我猜测AddDefaultIdentity是2.1版本中新加的,但问题在于它没有注入RoleManager,那我该怎么办?

6个回答

28

看起来微软终于明白并不是每个应用都需要角色并将它们分离。

请注意,AddDefaultIdentity 被声明为:

public static IdentityBuilder AddDefaultIdentity<TUser>(this IServiceCollection services) where TUser : class;

所以,您可以通过那个IdentityBuilder继续配置身份验证选项。您想要做的是:

因此,您可以继续通过IdentityBuilder来配置身份验证选项。您需要做的是:

services.AddDefaultIdentity<IdentityUser>().AddRoles<IdentityRole>();

幸运的是,他们也删除了IUserIRole限制,因此现在您可以在完全分离的程序集中使用模型,而无需安装数百个NuGet包。


2
太棒了!我可以确认这正是我想要的。感谢您的快速回复。 - Alan T
在这种情况下,我可以使用 AuthorizationHandlerContext.User.IsInRole 吗?如果不能,那么我应该使用 HttpContext.Current.User... 吗? - variable
@variable 嗯,这取决于您想在哪里检查角色以及检查角色的目的。但是,在ASP.NET Core中不存在HttpContext.Current。 - Camilo Terevinto
抱歉,我是指 HttpContext.User。我困惑的是 - 是否可以在没有身份验证的情况下使用角色(IsInRole等)。 - variable
@variable 是的,你可以。搜索类似“asp.net core roles -identity site:stackoverflow.com”的内容,这样的搜索应该能让你找到正确的方向。请注意,JWT 中角色的位置会影响你如何配置应用程序的启动。 - Camilo Terevinto
显示剩余3条评论

14

可能会对其他人有帮助:如果您通过脚手架将asp.net身份添加到现有项目中,则需要编辑IdentityHostingStartup.cs而不是在启动类中更改服务:

services.AddIdentity<AppUser, IdentityRole>()
                .AddDefaultUI()
                .AddRoles<IdentityRole>()
                .AddRoleManager<RoleManager<IdentityRole>>()
                .AddDefaultTokenProviders()
                .AddEntityFrameworkStores<authContext>();

然后您可以在种子中使用角色管理器。


1
AddRoles和AddRoleManager真的必要吗?或者至少,在.NET Core 2.2中是否需要?请参见:https://dev59.com/uFMI5IYBdhLWcg3wxuhI#55361961 - Jonathan B.

6
除了已经提供的答案外,尽管添加了.AddRoles<Identity>(),但我仍无法在控制器上使用Authorize(Roles = "Administrator")获得授权。由于某种原因,“角色声明似乎不影响IsUserInRole或带有角色名称的AuthorizeAttribute。”为了利用角色,建议使用以下ASP.NET 2.0方式:
services.AddIdentity<IdentityUser, IdentityRole>()
            .AddDefaultUI()
            .AddDefaultTokenProviders()
            .AddEntityFrameworkStores<ApplicationDbContext>();

这样,您可以使用角色,并为您构建身份页面。
请参考此 aspnet github 上的问题: Issue 1813

2
我之前也遇到过这个问题,但是没有在上面更新我的回复。现在我的IdentityHostingStartup.cs文件包含以下内容:services.AddIdentity<AppUser, IdentityRole>() .AddDefaultUI() .AddRoles<IdentityRole>() .AddRoleManager<RoleManager<IdentityRole>>() .AddDefaultTokenProviders() .AddEntityFrameworkStores<authContext>(); - Jonathan Galentine

4

从.Net Core 2.1开始,AddDefaultIdentity等同于以下内容:

  • AddIdentity
  • AddDefaultUI
  • AddDefaultTokenProviders

如果要添加角色功能,在 Startup.csConfigureServices 下,您可以使用 .AddRoles,如下所示:

services.AddDefaultIdentity<IdentityUser>()
    .AddRoles<IdentityRole>()            //<-- This line
    .AddEntityFrameworkStores<ApplicationDbContext>();

只需要这些。注销并重新登录非常重要。

记录一下(仅供测试),我尝试了 services.AddIdentity

IServiceCollection 不包含“AddIdentity”的定义...

以及 services.AddIdentityCore(在调试并显示页面之前没有错误):

InvalidOperationException: 未指定身份验证方案,并且未找到 DefaultChallengeScheme。可以使用 AddAuthentication(string defaultScheme) 或 AddAuthentication(Action configureOptions) 设置默认方案。

可能还有其他方法可以让后两个功能正常工作,但是我发布的 AddDefaultIdentity 代码足以让 User.IsInRole 和其他角色功能在 .NET Core 2.1(和3.1)中正常工作。


1
我之前也遇到了这个问题,我无法让角色起作用。
在我的项目中,我使用的是ASP.NET Core 2.1(可以在2.2中修复,参见链接),并且还生成了一些页面。
在互联网上进行长时间搜索后,我找到了这个解决方案(也在Issue 1813中提到)。
对于我来说,解决方案是(如文章所建议)添加以下行与IUserClaimsPrincipalFactory:
        services.AddScoped<IUserClaimsPrincipalFactory<IdentityUser>, 
            UserClaimsPrincipalFactory<IdentityUser, IdentityRole>>();

        services.AddDefaultIdentity<IdentityUser>()
            .AddRoles<IdentityRole>()
            .AddRoleManager<RoleManager<IdentityRole>>()
            .AddDefaultTokenProviders()
            .AddEntityFrameworkStores<TranslatorDbContext>();

谢谢,这有点帮助我重新启用了角色。 - Ole K

0
请注意,这段代码是有顺序要求的。如果你在添加EntityFrameworkStore后再加上AddRoles,那么会出现异常。
因此,请确保代码按照以下顺序排列:
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接