自定义权限验证

 

自定义权限验证需要实现抽象类 

public abstract class AuthorizationHandler<TRequirement> : IAuthorizationHandler where TRequirement : IAuthorizationRequirement

public abstract class AuthorizationHandler<TRequirement> : IAuthorizationHandler where TRequirement : IAuthorizationRequirement
{
protected AuthorizationHandler();
public virtual Task HandleAsync(AuthorizationHandlerContext context);
protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement);
}

实现接口

IAuthorizationRequirement

    //
    // 摘要:
    //     Represents an authorization requirement.
    public interface IAuthorizationRequirement
    {
    }

  

 

实现抽象类

 public class PermissionHandler : AuthorizationHandler<PermissionRequirement>
 {
     IMemoryCache memoryCache = new MemoryCache(Options.Create(new MemoryCacheOptions()
     {
         // SizeLimit = 1000,
         CompactionPercentage = 0.2,
     }));

     public IAuthenticationSchemeProvider Schemes;

     /// <summary>
     /// 构造函数注入
     /// </summary>
     public PermissionHandler(IAuthenticationSchemeProvider schemes)
     {
         Schemes = schemes;
         List<PermissionItem> list = new List<PermissionItem>
         {
             new PermissionItem{ actionName ="Get", controllerName ="Users", Role ="User" },
             new PermissionItem{ actionName ="Update", controllerName ="Users", Role ="User" },
         };
         memoryCache.Set<List<PermissionItem>>("permyyx", list);
     }

     // 重载异步处理程序
     protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
     {
         HttpContext httpContext1 = context.Resource as HttpContext;
         ControllerActionDescriptor? actionDescriptor =
             httpContext1.GetEndpoint().Metadata.Where(item => item is ControllerActionDescriptor)
             .OfType<ControllerActionDescriptor>().FirstOrDefault();
         AuthenticateResult result = await httpContext1.AuthenticateAsync(CustomerAuthenticationHandler.schemeName);

         //var attributes = actionDescriptor.MethodInfo.GetCustomAttributes(inherit: true);
         //bool isHaveAnonymous = attributes.Any(a => a.GetType().Name == "AllowAnonymousAttribute");
         //bool isHaveAuthorize = attributes.Any(a => a.GetType().Name == "AuthorizeAttribute");


         //如果没登录result.Succeeded为false
         if (result.Succeeded)
         {
             httpContext1.User = result.Principal;
             //当前访问的Controller
             string controllerName = actionDescriptor.ControllerName;
             //当前访问的Action
             string actionName = actionDescriptor.ActionName;
             string name = httpContext1.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Name)?.Value;
             string role = httpContext1.User.Claims.SingleOrDefault(s=>s.Type == ClaimTypes.Role)?.Value;
             List<PermissionItem> lst = memoryCache.Get<List<PermissionItem>>("perm" + name);

             if (lst.Where(w => w.controllerName == controllerName && w.actionName == actionName&&w.Role == role).Count() > 0)
             {
                 //如果在配置的权限表里正常走
                 context.Succeed(requirement);
             }
             else
             {
                 //不在权限配置表里 做错误提示
                 //如果是AJAX请求 (包含了VUE等 的ajax)
                 string requestType = httpContext1.Request.Headers["X-Requested-With"];//filterContext.HttpContext.Request.Headers["X-Requested-With"];
                 if (!string.IsNullOrEmpty(requestType) && requestType.Equals("XMLHttpRequest", StringComparison.CurrentCultureIgnoreCase))
                 {
                     //ajax 的错误返回
                     //filterContext.Result = new StatusCodeResult(499); //自定义错误号 ajax请求错误 可以用来错没有权限判断 也可以不写 用默认的

                     httpContext1.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                     context.Fail();
                 }
                 else
                 {
                     //普通页面错误提示 就是跳转一个页面
                     //httpContext.Response.Redirect("/Home/visitDeny");//第一种方式跳转
                     //filterContext.Result = new RedirectToActionResult("visitDeny", "Home", null);//第二种方式跳转
                     httpContext1.Response.Redirect("/Home/visitDeny");//第一种方式跳转
                     context.Fail();
                 }
             }
         }
         else
         {
             context.Fail();
         }
     }
 }

  

权限许可验证要求

public class PermissionRequirement : IAuthorizationRequirement
{
    /// <summary>
    /// 无权限action
    /// </summary>
    public string DeniedAction { get; set; } = "/Home/visitDeny";

    /// <summary>
    /// 认证授权类型
    /// </summary>
    public string ClaimType { internal get; set; }
    /// <summary>
    /// 默认登录页面
    /// </summary>
    public string LoginPath { get; set; } = "/Home/Login";
    /// <summary>
    /// 过期时间
    /// </summary>
    public TimeSpan Expiration { get; set; }
    /// <summary>
    /// 构造
    /// </summary>
    /// <param name="deniedAction"></param>
    /// <param name="claimType"></param>
    /// <param name="expiration"></param>
    public PermissionRequirement(string deniedAction, string claimType, TimeSpan expiration)
    {
        ClaimType = claimType;
        DeniedAction = deniedAction;
        Expiration = expiration;
    }

}

  

许可项

    public class PermissionItem
    {
        /// <summary>
        /// 用户或角色或其他凭据名称
        /// </summary>
        public virtual string Role { get; set; }
        /// <summary>
        /// 配置的Controller名称
        /// </summary>
        public virtual string controllerName { get; set; }
        /// <summary>
        /// 配置的Action名称
        /// </summary>
        public virtual string actionName { get; set; }
    }

  

注入

   var permissionRequirement = new PermissionRequirement(
      "/Home/visitDeny",// 拒绝授权的跳转地址
      ClaimTypes.Name,//基于用户名的授权
      expiration: TimeSpan.FromSeconds(60 * 5)//接口的过期时间
      );
   builder.Services.AddAuthorization(options =>
   {
       options.AddPolicy("Permission", policy => policy.Requirements.Add(permissionRequirement));
   });

   builder.Services.AddTransient<IAuthorizationHandler, PermissionHandler>();

  

  

 

posted on 2024-08-09 17:07  是水饺不是水饺  阅读(18)  评论(0)    收藏  举报

导航