• 周日. 7月 3rd, 2022

5G编程聚合网

5G时代下一个聚合的编程学习网

热门标签

asp.net core 权限认证

admin

11月 28, 2021

一、简单授权

ASP.NET Core 中的授权通过 AuthorizeAttribute 和其各种参数来控制。 在其页面中,通过 [Authorize] 属性应用于控制器、操作或 Razor 页面,限制对已通过身份验证的用户的访问。

示例如下:

[Authorize] 
public class AccountController : Controller { 
   public ActionResult Login() { 
   
   } 
   public ActionResult Logout() {

   }
 }

如果要对操作(而不是控制器)应用授权,请将属性应用于 AuthorizeAttribute 操作本身

示例如下:

public class AccountController : Controller { 
public ActionResult Login() { 

} 

[Authorize] 
public ActionResult Logout() { 

  } 
}

你还可以使用属性,以 AllowAnonymous 允许未通过身份验证的用户访问各个操作。 例如:

[Authorize] 
public class AccountController : Controller { 

  [AllowAnonymous] 
  public ActionResult Login() { 

  } 
  public ActionResult Logout() { 
  } 
}

二、基于角色的授权

基于角色的授权检查是声明性 — 的,开发人员将其嵌入到代码中、控制器或控制器内的操作,指定当前用户必须是其成员的角色才能访问请求的资源。

例如,以下代码将访问权限限制为属于角色成员的用户的任何操作:

[Authorize(Roles = "Administrator")] 
public class AdministrationController : Controller { }

多角色可以定义如下:

[Authorize(Roles = "HRManager,Finance")] 
public class SalaryController : Controller { }

如果应用多个属性,则访问用户必须是所有指定角色的成员;下面的示例要求用户必须是 PowerUser 和角色的成员 ControlPanelUser

[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")] 
public class ControlPanelController : Controller { }

三、基于策略的授权

基于策略的授权,其实就是要求用户必须满足指定的策略要求,这个策略一般都是用户的一些基本信息,如名字、角色或者其他,我们首先要在在配置函数中,添加一个策略如下:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();

    services.AddAuthorization(options =>
    {
        options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("EmployeeNumber"));
    });
}

如以上代码,要求用户的claim信息中包含EmployeeNumber属性

     var claims = new List<Claim>()
     {
      new Claim(ClaimTypes.Name,username),
      new Claim("UserId",currentUser.UID.ToString()),
      new Claim(ClaimTypes.Role, roleName),
      new Claim("EmployeeNumber",“1"),         
   };

那么在控制器中,只需要以下代码,并能实现对权限的控制

[Authorize(Policy = "EmployeeOnly")]
public IActionResult VacationBalance()
{
    return View();
}

基于策略的授权,

policy函数具有以下一些常用的函数:

AddAuthenticationSchemes(String[])
将指定的身份验证添加 schemes 到 AuthenticationSchemes 此实例的。

AddRequirements(IAuthorizationRequirement[])
将指定的添加 requirements 到 Requirements 此实例的。

Build()
AuthorizationPolicy根据此实例中的要求生成一个新的。

Combine(AuthorizationPolicy)
将指定的合并 policy 到当前实例中。

RequireAssertion(Func<AuthorizationHandlerContext,Boolean>)
将添加 AssertionRequirement 到当前实例中。

RequireAssertion(Func<AuthorizationHandlerContext,Task<Boolean>>)
将添加 AssertionRequirement 到当前实例中。

RequireAuthenticatedUser()
该实例强制对当前用户进行身份验证。

RequireClaim(String)
要求当前用户具有指定的声明。

RequireClaim(String, IEnumerable<String>)
这要求当前用户具有指定的声明,并且声明值必须是允许的值之一。

RequireClaim(String, String[])
这要求当前用户具有指定的声明,并且声明值必须是允许的值之一。

RequireRole(IEnumerable<String>)
该实例强制当前用户必须至少有一个指定的角色。

RequireRole(String[])
该实例强制当前用户必须至少有一个指定的角色。

RequireUserName(String)
强制当前用户与指定的名称匹配。

除以上功能之外,用于可以自定义策略,实现对页面的授权,其定义策略的基本方法如下:

1、实现IAuthorizationRequirement接口,定义一个策略规范

using Microsoft.AspNetCore.Authorization;

public class MinimumAgeRequirement : IAuthorizationRequirement
{
    public int MinimumAge { get; }

    public MinimumAgeRequirement(int minimumAge)
    {
        MinimumAge = minimumAge;
    }
}

2、实现策略检查器,其负责对策略进行检查,以下代码请求用户年纪,并且进行策略比较,实现授权

public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                   MinimumAgeRequirement requirement)
    {
        if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth &&
                                        c.Issuer == "http://contoso.com"))
        {
            //TODO: Use the following if targeting a version of
            //.NET Framework older than 4.6:
            //      return Task.FromResult(0);
            return Task.CompletedTask;
        }

        var dateOfBirth = Convert.ToDateTime(
            context.User.FindFirst(c => c.Type == ClaimTypes.DateOfBirth && 
                                        c.Issuer == "http://contoso.com").Value);

        int calculatedAge = DateTime.Today.Year - dateOfBirth.Year;
        if (dateOfBirth > DateTime.Today.AddYears(-calculatedAge))
        {
            calculatedAge--;
        }

        if (calculatedAge >= requirement.MinimumAge)
        {
            context.Succeed(requirement);
        }

        //TODO: Use the following if targeting a version of
        //.NET Framework older than 4.6:
        //      return Task.FromResult(0);
        return Task.CompletedTask;
    }
}

3、在ConfigureServices中添加策略检查代码,如下所示:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();
    services.AddAuthorization(options =>
    {
        options.AddPolicy("AtLeast21", policy =>
            policy.Requirements.Add(new MinimumAgeRequirement(21)));
    });
//添加一个可以注入的对象 services.AddSingleton
<IAuthorizationHandler, MinimumAgeHandler>(); }

4、如果要实现多个授权策略,可以实现继承如下接口

ublic class PermissionHandler : IAuthorizationHandler
{
    public Task HandleAsync(AuthorizationHandlerContext context)
    {
        var pendingRequirements = context.PendingRequirements.ToList();

        foreach (var requirement in pendingRequirements)
        {
            if (requirement is ReadPermission)
            {
                if (IsOwner(context.User, context.Resource) ||
                    IsSponsor(context.User, context.Resource))
                {
                    context.Succeed(requirement);
                }
            }
            else if (requirement is EditPermission ||
                     requirement is DeletePermission)
            {
                if (IsOwner(context.User, context.Resource))
                {
                    context.Succeed(requirement);
                }
            }
        }

        //TODO: Use the following if targeting a version of
        //.NET Framework older than 4.6:
        //      return Task.FromResult(0);
        return Task.CompletedTask;
    }

    private bool IsOwner(ClaimsPrincipal user, object resource)
    {
        // Code omitted for brevity

        return true;
    }

    private bool IsSponsor(ClaimsPrincipal user, object resource)
    {
        // Code omitted for brevity

        return true;
    }

四、策略授权提供程序IAuthorizationPolicyProvider 

通常,在使用 基于策略的授权时,通过调用 AuthorizationOptions.AddPolicy 作为授权服务配置的一部分来注册策略。 在某些情况下,可能无法 (或理想的) 以这种方式注册所有的授权策略。 在这些情况下,可以使用自定义 IAuthorizationPolicyProvider 来控制如何提供授权策略

internal class MinimumAgePolicyProvider : IAuthorizationPolicyProvider
{
    const string POLICY_PREFIX = "MinimumAge";

    // Policies are looked up by string name, so expect 'parameters' (like age)
    // to be embedded in the policy names. This is abstracted away from developers
    // by the more strongly-typed attributes derived from AuthorizeAttribute
    // (like [MinimumAgeAuthorize()] in this sample)
    public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
    {
        if (policyName.StartsWith(POLICY_PREFIX, StringComparison.OrdinalIgnoreCase) &&
            int.TryParse(policyName.Substring(POLICY_PREFIX.Length), out var age))
        {
            var policy = new AuthorizationPolicyBuilder(CookieAuthenticationDefaults.AuthenticationScheme);
            policy.AddRequirements(new MinimumAgeRequirement(age));
            return Task.FromResult(policy.Build());
        }

        return Task.FromResult<AuthorizationPolicy>(null);
    }
}

发表评论

您的电子邮箱地址不会被公开。