.net core 3.1 Policy 策略授权揭秘

交流QQ群:555913397
有什么问题可以加群大家一起交流

上次探究了core 3.1的自定义授权handler,这次带领大家来试试自带的Policy策略授权.好了废话不都说,一切都在代码中.

先创建存储许可的属性类

namespace CoreMvc.Utinity.Models
{
    /// 
    /// 许可项
    /// 
    public class PermissionItem
    {
        /// 
        /// 用户名称
        /// 
        public virtual string Name { get; set; }
        /// 
        /// 控制器名称
        /// 
        public virtual string ControllerName { get; set; }
        /// 
        /// 功能名称
        /// 
        public virtual string ActionName { get; set; }
    }
}

存储授权信息的缓存类

using System.Collections.Generic;
using CoreMvc.Utinity.Models;

namespace CoreMvc.Utinity
{
    public class PermissionDictionary
    {
        private static Dictionary> dictionary = new Dictionary>();
        public static void Add(string name, List permissionItems)
        {
            if (null == dictionary.GetValueOrDefault(name))
            {
                dictionary.Add(name, permissionItems);
            }
        }

        public static List Get(string name)
        {
            return dictionary.GetValueOrDefault(name, null);
        }
    }
}

创建许可条件

using System;
using Microsoft.AspNetCore.Authorization;

namespace CoreMvc.Utinity.Authentications.Requirement
{
    /// 
    /// 许可条件
    /// 
    public class PermissionRequirement : IAuthorizationRequirement
    {
        public string DeniedAction { get; set; }
        public string LoginPath { get; set; }
        public string ClaimType { get; set; }
        public TimeSpan Expiration { get; set; }
        public PermissionRequirement(string deniedAction, string loginPath, string claimType, TimeSpan expiration)
        {
            DeniedAction = deniedAction;
            LoginPath = loginPath;
            ClaimType = claimType;
            Expiration = expiration;
        }
    }
}

许可授权Handler

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CoreMvc.Utinity.Authentications.Requirement;
using CoreMvc.Utinity.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;

namespace CoreMvc.Utinity.Authentications
{
    public class PermissionAuthnenticationHandler : AuthorizationHandler
    {
        public IAuthenticationSchemeProvider Scheme;
        private readonly IHttpContextAccessor _httpContextAccessor;

        public PermissionAuthnenticationHandler(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
        {
            //.net core 3就改成了endpoint了,这里算是一个不小的坑
            if (context.Resource is Endpoint endpoint)
            {
                var controllActionDesription = endpoint.Metadata.GetMetadata();
                string controllerName = controllActionDesription.RouteValues["Controller"].ToLower();
                string actionName = controllActionDesription.RouteValues["Action"].ToLower();
                context.Succeed(requirement);
                List permissionList = PermissionDictionary.Get(context.User.Identity.Name);
                if (permissionList.Where(w => w.ControllerName == controllerName && w.ActionName == actionName).Count() > 0)
                {
                    //验证通过就正常执行
                    context.Succeed(requirement);
                }
                else
                {
                    //不通过就失败
                    context.Fail();
                }
            }
            await Task.CompletedTask;
        }
    }
}

创建Login,Action提供登陆授权

[AllowAnonymous]
public async Task Login()
{
    ClaimsIdentity claimsIdentity = new ClaimsIdentity(new List
    {
        new Claim(ClaimTypes.Name, "fqydhk"),
        new Claim(ClaimTypes.MobilePhone, "1315********"),
        new Claim(ClaimTypes.Email,"[email protected]")
    }, CookieAuthenticationDefaults.AuthenticationScheme);
    var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
    await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);
    //登陆成功创建权限信息
    List permissionList = new List();
    permissionList.Add(new PermissionItem() { Role = "fqydhk", ControllName = "home", ActionName = "authorization" });
    PermissionDictionary.Add("fqydhk", permissionList);
    string url = HttpContext.Request.Query["ReturnUrl"].ToString();
    HttpContext.Response.Redirect(url);
    return View();
}

创建一个需要授权才能访问的action

[Authorize(Policy = "permission")]
public IActionResult Authorization()
{
    ViewBag.Name = HttpContext.User.Identity.Name ?? "未登录,请登录";
    return View();
}

下面是 重中之重 在Startup.cs的ConfigureServices(IServiceCollection services)添加下面代码

PermissionRequirement permissionRequirement = new PermissionRequirement(
        deniedAction: "/home/denied",
        loginPath: "/home/login",
        claimType: ClaimTypes.Name,
        TimeSpan.FromSeconds(60 * 5));
    //添加授权支持
    services.AddAuthorization(options =>
    {
        //创建策略支持
        options.AddPolicy("Permission", policy =>
            {
                policy.Requirements.Add(permissionRequirement);
            });
        //添加鉴权支持
    }).AddAuthentication(options =>
    {
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        //添加cookie支持
    }).AddCookie(options =>
    {
        options.LoginPath = new PathString("/home/login");
        options.AccessDeniedPath = new PathString("/home/denied");
        options.ClaimsIssuer = "Cookie";
    });

在Startup.cs的Configure(IApplicationBuilder app, IWebHostEnvironment env)添加启用授权,非常重要,这算是一个小坑…


            app.UseAuthentication();

            app.UseAuthorization();

            app.UseCookiePolicy();

这里所有配置就已经完成了,如果有什么疑问欢迎留言或者加群讨论

你可能感兴趣的:(Asp.net,Core)