- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
问题:我调用RoleManager.CreateAsync()
和RoleManager.AddClaimAsync()
创建角色和关联的角色声明。然后我打电话UserManager.AddToRoleAsync()
将用户添加到这些角色。但是当用户登录时,角色和关联的声明都不会显示在 ClaimsPrincipal
中。 (即 Controller 的 User
对象)。这样做的结果是User.IsInRole()
总是返回 false,并且 User.Claims
返回的 Claims 集合不包含角色声明,并且 [Authorize(policy: xxx)]
注释不起作用。
我还应该补充一点,一种解决方案是恢复使用新的 services.AddDefaultIdentity()
(由模板化代码提供)返回调用services.AddIdentity().AddSomething().AddSomethingElse()
。我不想去那里,因为我在网上看到了太多关于我需要做什么来配置AddIdentity
的相互矛盾的故事。适用于各种用例。 AddDefaultIdentity
似乎无需添加大量流畅的配置即可正确完成大多数事情。
顺便说一句,我问这个问题是为了回答它......除非其他人给我一个比我准备发布的答案更好的答案。我问这个问题的另一个原因是,经过几周的搜索,我尚未找到在 ASP.NET Core Identity 2 中创建和使用角色和声明的良好端到端示例。希望这个问题中的代码示例可以帮助其他偶然发现它的人......
设置:我创建了一个新的 ASP.NET Core Web 应用程序,选择 Web 应用程序(模型- View - Controller ),并将身份验证更改为个人用户帐户。在最终的项目中,我执行以下操作:
在程序包管理器控制台中,更新数据库以匹配支架迁移:
update-database
添加 ApplicationUser
扩展类 IdentityUser
。这涉及到添加类,将一行代码添加到 ApplicationDbContext
并替换 <IdentityUser>
的每个实例与 <ApplicationUser>
项目中的各个地方。
新的ApplicationUser
类:
public class ApplicationUser : IdentityUser
{
public string FullName { get; set; }
}
更新后的ApplicationDbContext
类:
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{ }
// Add this line of code
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
}
在程序包管理器控制台中,创建新的迁移并更新数据库以合并 ApplicationUsers
实体。
add-migration m_001
update-database
在 Startup.cs
中添加以下代码行启用RoleManager
services.AddDefaultIdentity<ApplicationUser>()
.AddRoles<IdentityRole>() // <-- Add this line
.AddEntityFrameworkStores<ApplicationDbContext>();
向种子角色、声明和用户添加一些代码。此示例代码的基本概念是我有两个声明: can_report
允许持有人创建报告,并且can_test
允许持有者运行测试。我有两个角色,Admin
和Tester
。 Tester
角色可以运行测试,但无法创建报告。 Admin
角色可以两者兼得。因此,我将声明添加到角色中,并创建一个 Admin
测试用户和一个Tester
测试用户。
首先,我添加一个类,其唯一目的是包含此示例中其他地方使用的常量:
// Contains constant strings used throughout this example
public class MyApp
{
// Claims
public const string CanTestClaim = "can_test";
public const string CanReportClaim = "can_report";
// Role names
public const string AdminRole = "admin";
public const string TesterRole = "tester";
// Authorization policy names
public const string CanTestPolicy = "can_test";
public const string CanReportPolicy = "can_report";
}
接下来,我播种我的角色、声明和用户。我将此代码放在主登陆页面 Controller 中只是为了方便;它确实属于“启动”Configure
方法,但那是额外的六行代码......
public class HomeController : Controller
{
const string Password = "QwertyA1?";
const string AdminEmail = "admin@example.com";
const string TesterEmail = "tester@example.com";
private readonly RoleManager<IdentityRole> _roleManager;
private readonly UserManager<ApplicationUser> _userManager;
// Constructor (DI claptrap)
public HomeController(RoleManager<IdentityRole> roleManager, UserManager<ApplicationUser> userManager)
{
_roleManager = roleManager;
_userManager = userManager;
}
public async Task<IActionResult> Index()
{
// Initialize roles
if (!await _roleManager.RoleExistsAsync(MyApp.AdminRole)) {
var role = new IdentityRole(MyApp.AdminRole);
await _roleManager.CreateAsync(role);
await _roleManager.AddClaimAsync(role, new Claim(MyApp.CanTestClaim, ""));
await _roleManager.AddClaimAsync(role, new Claim(MyApp.CanReportClaim, ""));
}
if (!await _roleManager.RoleExistsAsync(MyApp.TesterRole)) {
var role = new IdentityRole(MyApp.TesterRole);
await _roleManager.CreateAsync(role);
await _roleManager.AddClaimAsync(role, new Claim(MyApp.CanTestClaim, ""));
}
// Initialize users
var qry = _userManager.Users;
IdentityResult result;
if (await qry.Where(x => x.UserName == AdminEmail).FirstOrDefaultAsync() == null) {
var user = new ApplicationUser {
UserName = AdminEmail,
Email = AdminEmail,
FullName = "Administrator"
};
result = await _userManager.CreateAsync(user, Password);
if (!result.Succeeded) throw new InvalidOperationException(string.Join(" | ", result.Errors.Select(x => x.Description)));
result = await _userManager.AddToRoleAsync(user, MyApp.AdminRole);
if (!result.Succeeded) throw new InvalidOperationException(string.Join(" | ", result.Errors.Select(x => x.Description)));
}
if (await qry.Where(x => x.UserName == TesterEmail).FirstOrDefaultAsync() == null) {
var user = new ApplicationUser {
UserName = TesterEmail,
Email = TesterEmail,
FullName = "Tester"
};
result = await _userManager.CreateAsync(user, Password);
if (!result.Succeeded) throw new InvalidOperationException(string.Join(" | ", result.Errors.Select(x => x.Description)));
result = await _userManager.AddToRoleAsync(user, MyApp.TesterRole);
if (!result.Succeeded) throw new InvalidOperationException(string.Join(" | ", result.Errors.Select(x => x.Description)));
}
// Roles and Claims are in a cookie. Don't expect to see them in
// the same request that creates them (i.e., the request that
// executes the above code to create them). You need to refresh
// the page to create a round-trip that includes the cookie.
var admin = User.IsInRole(MyApp.AdminRole);
var claims = User.Claims.ToList();
return View();
}
[Authorize(policy: MyApp.CanTestPolicy)]
public IActionResult Test()
{
return View();
}
[Authorize(policy: MyApp.CanReportPolicy)]
public IActionResult Report()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
我在“启动”ConfigureServices
中注册我的身份验证策略例程,就在调用services.AddMvc
之后
// Register authorization policies
services.AddAuthorization(options => {
options.AddPolicy(MyApp.CanTestPolicy, policy => policy.RequireClaim(MyApp.CanTestClaim));
options.AddPolicy(MyApp.CanReportPolicy, policy => policy.RequireClaim(MyApp.CanReportClaim));
});
哇。现在,(假设我已经记下了上面添加到项目中的所有适用代码),当我运行应用程序时,我注意到我的“内置”测试用户都无法访问 /home/Test
或/home/Report
页。此外,如果我在 Index 方法中设置断点,我会发现我的角色和声明不存在于 User
中。目的。但我可以查看数据库并看到所有角色和声明都在那里。
最佳答案
因此,回顾一下,问题是为什么 ASP.NET Core Web 应用程序模板提供的代码在用户登录时不将角色或角色声明加载到 cookie 中。
经过多次谷歌搜索和实验后,似乎必须对模板化代码进行两项修改才能使角色和角色声明发挥作用:
首先,您必须在 Startup.cs 中添加以下代码行以启用 RoleManager。 (OP 中提到了这一点魔法。)
services.AddDefaultIdentity<ApplicationUser>()
.AddRoles<IdentityRole>() // <-- Add this line
.AddEntityFrameworkStores<ApplicationDbContext>();
但是等等,还有更多!根据this discussion on GitHub ,让角色和声明显示在 cookie 中需要恢复到 service.AddIdentity
初始化代码,或者坚持使用 service.AddDefaultIdentity
并将此行代码添加到 ConfigureServices
:
// Add Role claims to the User object
// See: https://github.com/aspnet/Identity/issues/1813#issuecomment-420066501
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>, UserClaimsPrincipalFactory<ApplicationUser, IdentityRole>>();
如果您阅读上面引用的讨论,您会发现角色和角色声明显然已被弃用,或者至少没有得到热切支持。就我个人而言,我发现将声明分配给角色,将角色分配给用户,然后根据声明(根据用户的角色授予用户)做出授权决策非常有用。这为我提供了一种简单的声明性方式,例如允许多个角色访问一个函数(即包含用于启用该函数的声明的所有角色)。
但是您确实需要注意身份验证 cookie 中携带的角色和声明数据的数量。更多数据意味着每个请求发送到服务器的字节数更多,而且我不知道当您遇到 cookie 大小的某种限制时会发生什么。
关于asp.net-core - ASP.NET Core Identity 2 : User. IsInRole 始终返回 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53271496/
创建使用.NET框架的asp.net页面时,访问该页面的客户端是否需要在其计算机上安装.NET框架? IE。用户访问www.fakesite.com/default.aspx,如果他们没有安装框架,他
我阅读了很多不同的博客和 StackOverflow 问题,试图找到我的问题的答案,但最后我找不到任何东西,所以我想自己问这个问题。 我正在构建一个应用程序,其中有一个长时间运行的工作线程,它执行一些
已锁定。这个问题及其答案是locked因为这个问题是题外话,但却具有历史意义。目前不接受新的答案或互动。 我一直想知道为什么微软为这样一个伟大的平台选择了一个如此奇怪的、对搜索引擎不友好的名称。他们就
.Net Framework .Net .NET Standard的区别 1、.NET Framework 在未来.NET Framework或许成为过去时,目前还是有很多地方在使用的。这一套
如果有选择的话,您会走哪条路? ASP.NET Webforms + ASP.NET AJAX 或 ASP.NET MVC + JavaScript Framework of your Choice
我有一个 Web 服务,它通过专用连接通过 https 使用第三方 Web 服务,我应用了 ServicePointManager.ServerCertificateValidationCallbac
为什么我应该选择ASP.NET Web Application (.NET Framework)而不是ASP.NET Core Web Application (.NET Framework)? 我在
我在网络上没有找到任何关于包含 .NET Standard、.NET Core 和 .NET Framework 项目的 .NET 解决方案的公认命名约定。 就我而言,我们在 .NET 框架项目中有以
.NET Compact 是 .NET 的完美子集吗? 假设我考虑了屏幕大小和其他限制并避免了 .NET Compact 不支持的类和方法,或者 .NET Compact 是一个不同且不兼容的 GUI
我已经阅读了所有我能找到的关于 connectionManagement 中的 maxconnection 设置的文章:即 http://support.microsoft.com/kb/821268
我现在正在使用asp.net mvc,想知道使用内置的Json或 Json.Net哪个是更好的选择,但我不确定一个人是否比另一个人有优势。 另外,如果我确实选择沿用Json.Net的路线,那么我应该选
在 Visual Studio 中,您至少可以创建三种不同类型的类库: 类库(.NET Framework) 类库(.NET 标准) 类库(.NET Core) 虽然第一个是我们多年来一直使用的,但我
.NET 和 ASP.NET 之间有什么区别?它们有什么关系? 最佳答案 ASP.Net 基于 .Net 框架构建,提供有关 Web 开发的附加功能。 你可以去看看wikipedia article
在安装更高版本(3.0)之前,我需要安装.net框架1.1和2.0吗?或者单独安装 3.0 框架就足够了,并为在早期框架版本上编写的软件提供支持?谢谢 ,丽然 最佳答案 不,您不必安装以前的框架。 我
我正在开发一个项目,人们可以“更新”类别,例如更改类别的名称。我收到以下消息 This is called after clicking update 按钮 with the SQL statemen
.NET 类 System.Net.CookieContainer 线程安全吗? --更新:交 key 答复-- 是否有任何方法可以确保异步请求期间修改的变量(即 HttpWebRequest.Coo
我正在使用 JScript.NET 在我编写的 C# WinForms 应用程序中编写脚本。它工作得很好,但我只是尝试在脚本中放置一些异常处理,但我无法弄清楚如何判断我的 C# 代码抛出了哪种类型的异
我需要你的帮助, 比如我有一个小数类型的变量,我想这样取整。 例如 3.0 = 3 3.1 = 4 3.2 = 4 3.3 = 4 3.4 = 4 3.5 = 4 3.6 = 4 3.7 = 4 3.
我使用过这样的代码:http://msdn.microsoft.com/en-us/library/dw70f090.aspx在 ASP.NET 中工作之前访问数据库(2-3 年前)。我没有意识到我正
自 ConfigurationManager .NET Standard 中不存在,检索正在执行的程序集的应用程序设置的最佳方法是什么,无论是 web.config或 appSettings.{env
我是一名优秀的程序员,十分优秀!