04-授权策略

授权的过程核心就是验证完token有效之后,通过claims中的信息进行判断,使用特性[Authorize],并对claims中的信息进行校验的过程。

需要在Startup文件中的Configure函数中添加app.UseAuthorization();,在asp.net core3.1中新建了webapi之后就会自动包含此中间件。

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    #region jwt
    //身份验证又称“认证”、“鉴权”,是指通过一定的手段,完成对用户身份的确认。 
    //身份验证的目的是确认当前所声称为某种身份的用户,确实是所声称的用户。
    app.UseAuthentication();//注意添加这一句,启用验证,解析信息--就是读取token,解密token
    #endregion

    app.UseRouting();

    //授权一般是指对信息安全或计算机安全相关的资源定义与授予访问权限,尤指访问控制。
    //动词“授权Authorize”可指定义访问策略与接受访问。
    //例如,人力资源人员通常被授权访问员工记录,而这个策略通常被形式化为计算机系统中的访问控制规则。
    //在运行期间,系统使用已定义的访问控制规则决定是接受还是拒绝经过身份验证的访问请求。
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

这里只是描述一下基于policy的校验,其他基于角色等校验内部实现都是policy形式,只是进行了封装。

1)基础的policy校验

[Authorize(Roles = "ClaimRole")]
[HttpGet]
public async Task<string> IndexRole()
{
    return await Task.FromResult($"IndexRole");
}


[Authorize(Policy = "AdminPolicy")]
[HttpGet]
public async Task<string> IndexPolicy()
{
    return await Task.FromResult($"IndexPolicy");
}

两个控制器,分别是基于角色,基于policy的校验,

//基于policy的鉴权
services.AddAuthorization(options =>
{
    //内置的基础校验
    options.AddPolicy("AdminPolicy",
        policyBuilder => policyBuilder
        .RequireRole("ClaimRole")//Claim的Role是ClaimRole
        .RequireUserName("TestUser1")//Claim的Name是TestUser1
        .RequireClaim("Role")//必须有某个Cliam即可,不关心Claim的值
        .RequireClaim("Role", "Administrator", "Admin", "ADMIN")//必须有某个Cliam,对应的值必须是后面三个其中之一
        );
});

2)基于policy的扩展校验

[Authorize(Policy = "DoubleEmail")]
[HttpGet]
public async Task<string> IndexPolicyDouble()
{
    return await Task.FromResult($"IndexPolicyDouble");
}

//基于policy的鉴权
services.AddAuthorization(options =>
{
    //自定义的扩展校验
    options.AddPolicy("DoubleEmail", policyBuilder => policyBuilder
        .Requirements.Add(new DoubleEmailRequirement()));
});
services.AddSingleton<IAuthorizationHandler, My163MailHandler>();
services.AddSingleton<IAuthorizationHandler, QQMailHandler>();

/// <summary>
    /// 两种邮箱都能支持 
    /// </summary>
    public class DoubleEmailRequirement : IAuthorizationRequirement
    {
    }

    public class QQMailHandler : AuthorizationHandler<DoubleEmailRequirement>
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, DoubleEmailRequirement requirement)
        {
            if (context.User != null && context.User.HasClaim(c => c.Type == "EMail"))
            {
                var email = context.User.FindFirst(c => c.Type == "EMail").Value;
                Console.WriteLine(email);
                if (email.EndsWith("@qq.com", StringComparison.OrdinalIgnoreCase))
                {
                    context.Succeed(requirement);
                }
                else
                {
                    //context.Fail();//不设置失败
                }
            }
            return Task.CompletedTask;
        }
    }

    public class My163MailHandler : AuthorizationHandler<DoubleEmailRequirement>
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, DoubleEmailRequirement requirement)
        {
            if (context.User != null && context.User.HasClaim(c => c.Type == "EMail"))
            {
                var email = context.User.FindFirst(c => c.Type == "EMail").Value;
                Console.WriteLine(email);
                if (email.EndsWith("@163.com", StringComparison.OrdinalIgnoreCase))
                {
                    context.Succeed(requirement);
                }
                else
                {
                    //context.Fail();
                }
            }
            return Task.CompletedTask;
        }
    }

授权策略不管是采用jwt形式还是IdentityServer4或者其他方式进行token的颁发,都是一样的逻辑。只是对token的校验方式。

原文地址:https://www.cnblogs.com/vigorous/p/13595878.html