为什么 User.Identity 不包含 ClaimsTypes 的完整列表?

2024-03-18

我正在开发 ASP.NET Core Web 应用程序。我的 dotnet 版本是 3.1.401,我使用的是 Visual Studio Community 2019 版本 16.7.2。我在没有 ASP.NET Core Identity 的情况下使用 cookie 身份验证。一切都运转良好。

在我的页脚_Layout视图,我显示经过身份验证的用户的名称,我可以轻松访问它@User.Identity.Name。但我也想添加他的角色。我首先认为可以使用这个@User.Identity.Role但事实并非如此。

以下是成功登录后创建的声明列表:

Admin loggedAdmin = form.LoginCheck();

if (loggedAdmin != null)
{
    if (!loggedAdmin.Deleted || !loggedAdmin.IsActive)
    {
        string name = StringCustomMethods.GetInitialsFromFirstName(loggedAdmin.FName) + loggedAdmin.LName;

        var userClaims = new List<Claim>()
        {
            new Claim(ClaimTypes.Name, name),
            new Claim(ClaimTypes.Role, loggedAdmin.Role),
            new Claim("Id", loggedAdmin.Id.ToString()),
            new Claim("RoleType", loggedAdmin.Role),  <---- created to access it easily
        };

        // Passes list of claims and AuthenticationTypes
        var claimsListAndAuthTypes = new ClaimsIdentity(userClaims, "User Identity");

// etc...

然后,我在列表中创建了一个带有字符串类型的新声明,以便能够使用它:@Context.User.FindFirst("RoleType").Value

我认为这很愚蠢,因为我已经提出了索赔ClaimTypes.Role。但这是我找回它的唯一简单方法。但也许我还缺少另一种“简单的方法”。我是初学者...

另一个问题是为什么只有Name, IsAuthenticated and AuthenticationType可通过以下方式访问的属性"@User.Identity..."。最后,有一个内置声明列表,您可以使用并添加到ClaimsPrincipal因此,您希望它们像上述 3 个那样易于访问。

Thanks


The ClaimsIdentity https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity?view=netcore-3.1允许配置其默认声明类型NameClaimType https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity.nameclaimtype?view=netcore-3.1 and RoleClaimType https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity.roleclaimtype?view=netcore-3.1然后框架的不同部分将其用作处理声明值的快捷方式。

这些快捷方式之一是ClaimsIdentity.Name https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity.name?view=netcore-3.1它仅返回具有配置的默认声明类型的身份的第一个声明的值NameClaimType。另一个捷径是ClaimsPrincipal.IsInRole https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsprincipal.isinrole?view=netcore-3.1检查身份是否具有类型声明RoleClaimType与指定值。

这些名称和角色的可配置声明类型背后的想法是,不存在one每个的标准索赔类型。例如,对于您可能想要使用的名称ClaimTypes.Name https://learn.microsoft.com/en-us/dotnet/api/system.identitymodel.claims.claimtypes.name?view=netframework-4.8(哪个值是"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"), or ClaimTypes.NameIdentifier https://learn.microsoft.com/en-us/dotnet/api/system.identitymodel.claims.claimtypes.nameidentifier?view=netframework-4.8(哪个值是"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").

如果您有一个与其他非 Microsoft 平台集成的系统,您可能想坚持使用更简单的方法JWT 声明类型 https://www.iana.org/assignments/jwt/jwt.xhtml反而。在那里,您可以使用声明类型"name", or "preferred_username"。同样,在某些设置中,角色声明类型可能只是"role".

所以基本上,索赔类型并没有真正标准化,您可能必须在不同的应用程序和场景中选择不同的类型。没关系。但由于 .NET 类型中有一些实用程序,因此如果您希望这些实用程序正常工作,您可能必须指定正在使用的名称和角色声明类型。


至于索赔检索,正如您所见,您不仅可以访问属性。相反,有一些实用方法允许您查询声明。最常见的是ClaimsPrincipal.FindFirst https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsprincipal.findfirst?view=netcore-3.1它返回特定类型的第一个声明。如果你只是想检查是否存在,你也可以使用ClaimsPrincipal.HasClaim https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsprincipal.hasclaim?view=netcore-3.1.

在ASP.NET Core内部,你还有非常有用的扩展方法ClaimsPrincipal.FindFirstValue https://learn.microsoft.com/de-de/dotnet/api/system.security.claims.principalextensions.findfirstvalue?view=aspnetcore-3.1它将仅返回特定声明类型的声明值。这可能是您大部分时间都会使用的。

作为个人建议,我还会考虑创建您自己的一组特定于应用程序的扩展方法ClaimsPrincipal它允许您直接检索特定于您的应用程序的声明类型的值。这还使您能够直接将声明值解析为您想要的任何类型(因为声明仅基于字符串)。例如,这可能如下所示:

public static class ClaimsPrincipalExtensions
{
    public static string GetName(this ClaimsPrincipal user)
        => user.FindFirstValue(ClaimTypes.Name);

    public static string GetRole(this ClaimsPrincipal user)
        => user.FindFirstValue(ClaimTypes.Role);

    public static int GetId(this ClaimsPrincipal user)
        => int.Parse(user.FindFirstValue("id"));
}

然后就可以直接在上面使用这些扩展方法了User整个 ASP.NET Core 中存在的对象,例如在视图或控制器中:

<div class="user-info">
    <strong>@User.GetName() (@User.GetId())</strong>
    Current role: @User.GetRole()
</div>

最后一点:通常,一个身份应该能够同时担任多个角色。这就是为什么该框架没有单一的Role属性来获得single角色声称有价值,但给你一个IsInRole方法来根据用户所在的角色集检查单个角色值。当然,这只是默认假设:如果您的应用程序仅使用单个角色值,那么将角色声明视为任何角色声明都是完全可以的。您只期望单个值的其他声明。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 User.Identity 不包含 ClaimsTypes 的完整列表? 的相关文章

随机推荐

  • 使用 Scenform 将 SceneView 加载到片段中后出现黑屏

    我正在开发一个项目 该项目将在一个片段中包含 3D 模型查看器 为了做到这一点 我决定使用 sceneform 在尝试在我的选项卡片段中显示 SceneView 后 我遇到了 SceneView 的问题 一切都是根据示例和 scenefor
  • 如何在 iPhone 应用程序中保持 Web 服务器的登录状态?

    简而言之 我想要一个 iPhone 应用程序 使用输入的用户名和密码值登录到 Web 服务器 然后维护此登录 以便用户可以将数据 POST 到服务器 这只是使用cookie的问题吗 如果是这样 如何执行检查以验证用户是否已登录 Thanks
  • 如何通过 Maven 或 Gradle 在项目中使用“预览 API”和/或“孵化 API”

    作为当前 Java 增强开发过程的一部分OpenJDK https en wikipedia org wiki OpenJDK项目中 一些正在开发的 Java 新功能以预发布形式提供预览API https openjdk java net
  • Python 请求使用证书值而不是路径

    我正在使用 python 请求模块进行 POST 调用 import requests response requests post foo url json foo bar headers foo headers verify path
  • html 中的工具提示

    我有一个 div 需要使用线条和框 将包含一条消息 进行识别 如下面的模型图像所示 2 和 3 线条和矩形框 彼此固定并且可拖动 1 线条 可以向任意方向拉伸 我已经创建了盒子 但我不知道如何在其上附加一条线 这是我尝试过的 JSFIDDL
  • Powershell:多维数组作为函数的返回值

    我在 PowerShell 中的二维数组方面遇到了一些问题 这就是我想做的 我创建了一个应该返回二维数组的函数 调用该函数时 我希望返回值是一个新的二维数组 为了更好地理解 我添加了一个示例函数 如下 function fillArray
  • HTTP 状态 500 - 实例化 servlet 类 org.springframework.web.servlet.DispatcherServlet 时出错

    请不要将此帖子标记为重复帖子 因为我在相关问题中没有找到任何好的资源 使用的技术 Spring MVC 4 3 3 RELEASE 摇篮3 1 雄猫9 0 我创建了一个动态 Web 项目 当我运行它时 出现以下错误 HTTP Status
  • Java线程安全——多个原子操作?

    我只是一个非开发者 想成为一名开发者 所以我的问题可能非常简单 我只是测试 Java 多线程的东西 这不是真正的代码 我想知道如何在 Java 中同时更新两个成员变量 以防我们希望它们同步 举个例子 public class Testing
  • 选择时列名无效

    我有一张桌子叫Jobs具有以下列名称 JobID Name and Value 该表就像只有一个条目一样被填满 JobID 1 Name 测试工作 Value 10 我想要做select from Jobs where Name TestJ
  • Visual Basic 6 ListView 的自动化支持

    I need to get value text of control via automation interface coding with C C I tried with UI Automation API https msdn m
  • 是什么让GDB拒绝崩溃?

    我在这里不知所措 我正在用 C 编写一个编译器 出于爱好 并使用 GDB 7 3 在 amd64 Linux 2 6 32 上使用 GCC 4 6 1 进行编译 除了通常的 I 等之外 标志还有 Wall Wextra O0 g 我有一个函
  • 无法在 Octave 3.8 Ubuntu 中安装 Octave-forge 其他包

    我是 Octave 的新手 尝试安装 杂项 包以使用 GNU 单元 安装失败 我试过 apt get 安装八度杂项 deb 软件包已安装 但未在 Octave 3 8 中列出 通过 gt gt pkg list 然后我尝试 gt pkg i
  • Derby DB SQL,从行号开始选择行

    如何在 Derby DB 的 SQL 查询中从 X 行到 Y 行进行选择 例如 我想选择第 15 30 行 但不是前 15 行 选择从行号 30 开始的所有行 我尝试了 LIMIT 和 ROWNUM 但它们不起作用 我怎样才能在德比做到这一
  • php中如何检测ajax跨域请求

    对于普通的ajax请求我使用 strtolower SERVER HTTP X REQUESTED WITH xmlhttprequest 但这不适用于跨域请求 我能怎么做 Edit2 如果您以这种方式使用 jQuery ajax 函数 v
  • PHP 命名空间自动加载必须使用文件夹吗?

    我对在 php 中实现命名空间感到非常困惑 尤其是在别名导入类方面 我已经按照本教程中的教程进行操作 利用 PHP V5 3 命名空间实现可读且可维护的代码 http www ibm com developerworks opensourc
  • 带有可选字段的 JPA 存储库 findAll

    我有一个控制器尝试使用可选字段进行搜索 JPA实体类定义为 package demo import javax persistence Entity public class UploadFile Id GeneratedValue str
  • 安全策略文件和jar

    我有 RMI 应用程序 所以我需要使用策略文件 我的策略文件很简单 conf txt grant permission java security AllPermission 我从 eclipse 运行我的应用程序没有任何问题 我已将 Dj
  • HTML5、Canvas 和 FireFox

    我对下面所示的 HTML5 Canvas 代码有几个问题 该文本不会出现在 Firefox 3 6 中 它会出现在 Chrome 中 关于 ctx 变量 ctx c getContext 2d 是否应该反复重用该变量以在同一画布上创建其他矩
  • 现代 Fortran:无标签的输出格式

    我正在寻找一种不使用标签来指定输出格式的方法 为了理解我的意思 用标签 write 1001 icount x y 1001 format i5 f5 2 e12 3 没有标签应该是我放的format i5 f5 2 e12 3 在 wri
  • 为什么 User.Identity 不包含 ClaimsTypes 的完整列表?

    我正在开发 ASP NET Core Web 应用程序 我的 dotnet 版本是 3 1 401 我使用的是 Visual Studio Community 2019 版本 16 7 2 我在没有 ASP NET Core Identit