c# .net core项目角色授权机制

前言

角色授权机制是确保应用程序安全性的重要组成部分,它允许开发者根据用户的角色来限制对应用程序中不同资源的访问。

基本概念:

角色授权基于用户角色的访问控制,即根据用户所属的角色来决定其能够访问的资源或执行的操作。在.NET Core中,这通常与身份认证(Authentication)一起使用,以确保只有经过验证的用户才能被授权访问特定资源。

案例

在上一篇blog 中,我们完成了对.net Core项目添加了JWT签名的生成与校验,这里,我们基于上一篇blog中演示的代码中进行改进,在jwt中添加Role信息。

c# .net core项目中使用JWT进行权限校验http://t.csdnimg.cn/XjqqX

角色枚举

首先,我们新建一个枚举AuthorizeRoleName,用于表示不同的角色 。

cs 复制代码
public enum AuthorizeRoleName
{
    Administrator,  
    Editor,  
    Viewer  
}

用户信息增加角色

然后在UserRes中添加一个新的属性RoleName,用于填写用户角色。

cs 复制代码
public class UserRes
{
    /// <summary>
    /// 用户名
    /// </summary>
    [Required]
    public string Name { get; set; }

    /// <summary>
    /// 密码
    /// </summary>
    [Required]
    public string Password { get; set; }

    /// <summary>
    /// 用户角色
    /// </summary>
    [Required]
    public AuthorizeRoleName RoleName { get; set; }
}

再在生成token的时候往claims中加入

cs 复制代码
new Claim("RoleName",user.RoleName.ToString()),

这样,我们调用GetToken接口时就可以设置角色,并存储到token中。

我们来进行测试一下,将接口获取到的token放到在线解析工具JSON Web Tokens - jwt.io中解析一下,可以看到已经有RoleeName的信息了。

增加AdminAuthorizeAttribute类

  • 用途 :这是一个自定义的属性(Attribute),继承自TypeFilterAttribute。它允许开发者通过在其上指定AuthorizeRoleName枚举值,来标记哪些类或方法需要特定的角色授权。
  • 构造函数 :接收一个AuthorizeRoleName枚举类型的参数role,该参数用于指定允许访问的角色。在构造函数中,它调用了基类TypeFilterAttribute的构造函数,并传入了AdminAuthorizeFilter类型的实例,同时将role作为参数传递给AdminAuthorizeFilter
  • 特性 :通过AttributeUsage特性指定了这个自定义属性可以应用于类(Class)或方法(Method),并且允许多次应用(AllowMultiple = true),还可以被子类继承(Inherited = true)。
cs 复制代码
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class AdminAuthorizeAttribute : TypeFilterAttribute
{
    public AuthorizeRoleName Role { get; }

    public AdminAuthorizeAttribute(AuthorizeRoleName role) : base(typeof(AdminAuthorizeFilter))
    {
        Role = role;
        Arguments = new object[] { role };
    }
}

:base(typeof(AdminAuthorizeFilter)): 这是构造函数的初始化器(Constructor Initializer),它调用了基类TypeFilterAttribute的构造函数,并传递了一个参数typeof(AdminAuthorizeFilter)。typeof(AdminAuthorizeFilter)是一个Type对象,它表示AdminAuthorizeFilter类的类型信息。这里,它告诉TypeFilterAttribute,当这个自定义属性被应用时,应该使用AdminAuthorizeFilter类作为过滤器。

增加AdminAuthorizeFilter类

  • 接口实现 :实现了IAuthorizationFilter接口,这意味着它将在MVC或Razor Pages的授权流程中被调用。
  • 构造函数 :接收一个AuthorizeRoleName枚举类型的参数role,这个参数是通过AdminAuthorizeAttribute传递过来的,用于指定允许访问的角色。
  • OnAuthorization方法 :这是授权逻辑的核心。首先,它检查用户是否已认证(即是否已经登录)。如果用户未认证,则返回一个ChallengeResult,这通常会导致用户被重定向到登录页面。如果用户已认证,则通过调用GetCurrentUserRole方法获取用户的角色,并与允许的角色进行比较。如果用户角色不匹配,则返回一个ForbidResult,这通常表示用户没有权限访问该资源,并返回403 Forbidden状态码。
  • GetCurrentUserRole方法 :这是一个辅助方法,用于从HttpContext中提取用户的角色信息。它查找用户声明(Claims)中类型为"RoleName"的声明,并将其值尝试转换为AuthorizeRoleName枚举类型。如果转换成功,则返回该枚举值;如果失败或找不到角色声明,则抛出异常。
cs 复制代码
public class AdminAuthorizeFilter : IAuthorizationFilter
{
    private readonly AuthorizeRoleName _role;

    public AdminAuthorizeFilter(AuthorizeRoleName role)
    {
        _role = role;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        // 检查用户是否已认证  
        if (!context.HttpContext.User.Identity.IsAuthenticated)
        {
            context.Result = new ChallengeResult();
            return;
        }

        // 检查用户是否属于指定的角色通,常涉及到检查用户的Claims或其他安全令牌中的信息  
        // 我们有一个方法GetCurrentUserRole()来获取当前用户的角色  
        var userRole = GetCurrentUserRole(context.HttpContext); 

        if (userRole != _role)
        {
            context.Result = new ForbidResult(); // 或者返回403 Forbidden,取决于你的需求  
        }
    }

    // 
    private AuthorizeRoleName GetCurrentUserRole(HttpContext context)
    {
        var user = context.User;
        var roleClaim = user.Claims.FirstOrDefault(c => c.Type == "RoleName");

        if (roleClaim != null)
        {
            // 将 Claim 的 Value 转换为 AuthorizeRoleName 枚举  
            // 这里需要实现一个转换逻辑,因为 Claim 的 Value 是字符串   
            if (Enum.TryParse<AuthorizeRoleName>(roleClaim.Value, true, out var role))
            {
                return role;
            }

            throw new InvalidOperationException("无法确定用户的角色!");
        }

        throw new InvalidOperationException("角色信息为空!");
    }
}

调整获取用户信息接口

在之前的GetUser接口上增加属性标签

cs 复制代码
[AdminAuthorize(AuthorizeRoleName.Administrator)]

表示只有role为 Administrator 的角色才能访问此接口。

测试一下!

当GetToken时设置Role为0,即(Administrator )时,获得的token去访问GetUser时是可以的。

设置为其他时,则断点会进入这里,接口返回403

项目代码

该项目的案例源代码我已经上传至gitee,需要的可自取

AuthenticationAndAuthorization: .net Core Web Api的Token生成,JWT签名,验证与授权 (gitee.com)https://gitee.com/libihao520/authentication-and-authorization

相关推荐
码农君莫笑15 小时前
Blazor项目中使用EF读写 SQLite 数据库
linux·数据库·sqlite·c#·.netcore·人机交互·visual studio
_oP_i18 小时前
.NET Core 项目配置到 Jenkins
运维·jenkins·.netcore
A^mber3 天前
基于.NetCore 的 AI 识别系统的设计与实现
人工智能·.netcore
Jeffrey~~5 天前
.Net_比对Json文件是否一致
c#·json·.net·.netcore
吳所畏惧5 天前
C#轻松实现Winform监控文件夹变化以及监控文件新增、修改、删除、重命名等操作保姆级详细教程
开发语言·windows·c#·.net·.netcore
CS软件开发框架5 天前
C/S软件授权注册系统-轻量级WebApi服务器介绍
运维·服务器·visualstudio·c#·.net·.netcore
鸠摩智首席音效师6 天前
如何使用 Docker 容器化 .NET Core 应用程序 ?
docker·容器·.netcore
洱海之月6 天前
.Net Core框架创建一个Windows服务类型的应用程序
.netcore
洱海之月6 天前
.Net Core配置使用Log4Net日志记录
.netcore
张3蜂6 天前
.NET Core 各版本特点、差异及适用场景详解
asp.net·.net·.netcore