.NetCoreAOP之AuthorizeAttribute

博客 分享
0 163
张三
张三 2022-02-27 00:55:50
悬赏:0 积分 收藏

.Net Core AOP之AuthorizeAttribute

一、简介

在.net core 中Filter分为以下六大类:

1、AuthorizeAttribute(权限验证)

2、IResourceFilter(资源缓存)

3、IActionFilter(执行方法前后的记录)

4、IResultFilter(结果生成前后扩展)

5、IAlwaysRun(响应结果的补充)

6、IExceptionFilter(异常处理)

二、AuthorizeAttribute(权限验证)

认证授权分为三种,如下:

1、基于角色授权

1.1、配置Startup.cs 类,使用Cookie及角色授权方式访问 —— 修改 ConfigureServices 与 Configure方法

public void ConfigureServices(IServiceCollection services)        {            services.AddControllersWithViews();            {                 // ************1、添加鉴权和授权逻辑**************************                services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>                {                    options.LoginPath = new PathString("/Login/LoginView"); // 登录地址                    options.AccessDeniedPath = new PathString("/Login/AccessDenied"); // 无权限访问需要跳转的页面地址                    options.LogoutPath = new PathString("/Login/LoginOff"); // 登出地址                    options.ExpireTimeSpan = TimeSpan.FromMinutes(1); // cookie有效时间(这里设置的1分钟有效时间)                    options.Cookie = new CookieBuilder                    {                        // cookie名称,Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")取得是当前环境变量的名称,用户可自定义                        Name = $"WebUI_{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}"                     };                });                services.AddAuthorization();                // **********************************************************            }        }        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)        {            if (env.IsDevelopment())            {                app.UseDeveloperExceptionPage();            }            else            {                app.UseExceptionHandler("/Home/Error");            }            app.UseStaticFiles();            app.UseRouting();            // ***************2、鉴权*******************            app.UseAuthentication();            // 授权            app.UseAuthorization();                        app.UseEndpoints(endpoints =>            {                endpoints.MapControllerRoute(                    name: "default",                    pattern: "{controller=Login}/{action=LoginView}/{id?}");            });        }

 

1.2、使用授权的时候在Action或controller上打上Authorize特性并赋值Role属性,表示该方法只能由Admin的角色访问

public class LoginController : Controller    {        // 登录页面        public IActionResult LoginView()        {            return View();        }        /// <summary>        /// 登录方法        /// </summary>        /// <returns></returns>        [AllowAnonymous]        public async Task<IActionResult> Login()        {            var claims = new List<Claim>            {                new Claim(ClaimTypes.Name,"xiaohemiao"),                new Claim(ClaimTypes.Role,"Admin")            };            var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme                , new ClaimsPrincipal(claimsIdentity)                , new AuthenticationProperties()                {                    ExpiresUtc = DateTime.UtcNow.AddMinutes(1)                });                        return Redirect("/Login/Index");        }        /// <summary>        /// 登录成功之后跳转的页面        /// </summary>        /// <returns></returns>        [Authorize(Roles = "Admin")]        public IActionResult Index()        {            return View();        }        /// <summary>        /// 登出        /// </summary>        /// <returns></returns>        public async Task<IActionResult> LoginOff()        {            await HttpContext.SignOutAsync();            return Redirect("/Login/LoginView");        }        /// <summary>        /// 无权限页面        /// </summary>        /// <returns></returns>        public IActionResult AccessDenied()        {            return View();        }            }

 

2、基于声明授权

修改基于标题1的相关代码

public void ConfigureServices(IServiceCollection services)        {            services.AddControllersWithViews();            {                 // ************1、添加鉴权和授权逻辑**************************                services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>                {                    options.LoginPath = new PathString("/Login/LoginView"); // 登录地址                    options.AccessDeniedPath = new PathString("/Login/AccessDenied"); // 无权限访问需要跳转的页面地址                    options.LogoutPath = new PathString("/Login/LoginOff"); // 登出地址                    options.ExpireTimeSpan = TimeSpan.FromMinutes(1); // cookie有效时间(这里设置的1分钟有效时间)                    options.Cookie = new CookieBuilder                    {                        // cookie名称,Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")取得是当前环境变量的名称,用户可自定义                        Name = $"WebUI_{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}"                     };                });                services.AddAuthorization(options => {                    // 当角色是Admin和SuperAdministrator才可以访问                    options.AddPolicy("AdministratorOnly", policy => policy.RequireClaim(ClaimTypes.Role, "Admin", "SuperAdministrator"));                });                // **********************************************************            }        }        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)        {            if (env.IsDevelopment())            {                app.UseDeveloperExceptionPage();            }            else            {                app.UseExceptionHandler("/Home/Error");            }            app.UseStaticFiles();            app.UseRouting();            // ***************2、鉴权*******************            app.UseAuthentication();            // 授权            app.UseAuthorization();                        app.UseEndpoints(endpoints =>            {                endpoints.MapControllerRoute(                    name: "default",                    pattern: "{controller=Login}/{action=LoginView}/{id?}");            });        }

 

public class LoginController : Controller    {        // 登录页面        public IActionResult LoginView()        {            return View();        }        /// <summary>        /// 登录方法        /// </summary>        /// <returns></returns>        [AllowAnonymous]        public async Task<IActionResult> Login()        {            var claims = new List<Claim>            {                new Claim(ClaimTypes.Name,"xiaohemiao"),                new Claim(ClaimTypes.Role,"Admin")            };            var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme                , new ClaimsPrincipal(claimsIdentity)                , new AuthenticationProperties()                {                    ExpiresUtc = DateTime.UtcNow.AddMinutes(1)                });                        return Redirect("/Login/Index");        }        /// <summary>        /// 登录成功之后跳转的页面        /// </summary>        /// <returns></returns>        [Authorize(Policy = "AdministratorOnly")]        public IActionResult Index()        {            return View();        }        /// <summary>        /// 登出        /// </summary>        /// <returns></returns>        public async Task<IActionResult> LoginOff()        {            await HttpContext.SignOutAsync();            return Redirect("/Login/LoginView");        }        /// <summary>        /// 无权限页面        /// </summary>        /// <returns></returns>        public IActionResult AccessDenied()        {            return View();        }            }

 

3、自定义策略授权

3.1、定义权限策略

 

public class PermissionRequirement: IAuthorizationRequirement    {    }

 

3.2、再定义个策略处理类

public class RoleAuthorizationHandler : AuthorizationHandler<PermissionRequirement>    {        private readonly ILogger<RoleAuthorizationHandler> _logger;        private readonly IHttpContextAccessor _httpContextAccessor;        public RoleAuthorizationHandler(ILogger<RoleAuthorizationHandler> logger, IHttpContextAccessor httpContextAccessor)        {            _logger = logger;            this._httpContextAccessor = httpContextAccessor;        }        public override Task HandleAsync(AuthorizationHandlerContext context)        {            var mvcContext = _httpContextAccessor.HttpContext;            var user = context.User.FindFirst(ClaimTypes.Role)?.Value;                       if (mvcContext.User.Identity.IsAuthenticated)            {                var routes = mvcContext.GetRouteData();                var controller = routes.Values["controller"]?.ToString()?.ToLower();                var action = routes.Values["action"]?.ToString()?.ToLower();                var activeTime = mvcContext.User.FindFirst(ClaimTypes.Expired);                // 是否登录超时                if (activeTime == null || Convert.ToDateTime(activeTime.Value) < DateTime.Now)                {                    // 登录超时自动跳转到登录页面                    mvcContext.Response.Redirect("/Login/LoginView");                    context.Succeed(context.Requirements.FirstOrDefault());                    return Task.CompletedTask;                }                var hasRole = mvcContext.User.HasClaim(c => c.Type == ClaimTypes.Role);                if (!hasRole)                {                    //用户未在系统添加,即使登录成功,也要提示没有权限                    context.Fail();                    return Task.CompletedTask;                }                var menuPaths = AuthorizationMenuPath(user);                string route = $"/{controller}";                               var actionRoute = $"/{controller}/{(routes.Values["action"] ?? "Index")}".ToLower();                if (menuPaths.Any(m => m.ToLower().Contains($"/{controller}/")) || menuPaths.Any(m => m.ToLower() == route) || menuPaths.Any(m => m.ToLower() == actionRoute))                    context.Succeed(context.Requirements.FirstOrDefault());                else context.Fail();//会默认跳转 accessdenied视图                            }            else                context.Fail();            return Task.CompletedTask;        }        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)        {            throw new NotImplementedException();        }        /// <summary>        /// 权限动态缓存类 临时替代数据库        /// </summary>        /// <param name="roleName">角色名称</param>        /// <returns></returns>        private List<string> AuthorizationMenuPath(string roleName)        {            switch (roleName)            {                case "Admin":                    return new List<string>() { "/Login/Index" };                default:                    return new List<string>() { "/Login/Index" };            }                    }    }

 

3.3、修改 ConfigureServices 与 Configure方法

public void ConfigureServices(IServiceCollection services)        {            services.AddControllersWithViews();            {                // ************3、注入自定义策略**************************                services.AddSingleton<IAuthorizationHandler, RoleAuthorizationHandler>();                // ************1、添加鉴权和授权逻辑**************************                services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>                {                    options.LoginPath = new PathString("/Login/LoginView"); // 登录地址                    options.AccessDeniedPath = new PathString("/Login/AccessDenied"); // 无权限访问需要跳转的页面地址                    options.LogoutPath = new PathString("/Login/LoginOff"); // 登出地址                    options.ExpireTimeSpan = TimeSpan.FromMinutes(1); // cookie有效时间(这里设置的1分钟有效时间)                    options.Cookie = new CookieBuilder                    {                        // cookie名称,Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")取得是当前环境变量的名称,用户可自定义                        Name = $"WebUI_{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")}"                     };                });                services.AddAuthorization(options =>                {                    options.AddPolicy("RolePolicy", policy =>policy.Requirements.Add(new PermissionRequirement()));                                   });                services.AddHttpContextAccessor();                // **********************************************************            }        }        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)        {            if (env.IsDevelopment())            {                app.UseDeveloperExceptionPage();            }            else            {                app.UseExceptionHandler("/Home/Error");            }            app.UseStaticFiles();            app.UseRouting();            // ***************2、鉴权*******************            app.UseAuthentication();            // 授权            app.UseAuthorization();                        app.UseEndpoints(endpoints =>            {                endpoints.MapControllerRoute(                    name: "default",                    pattern: "{controller=Login}/{action=LoginView}/{id?}");            });        }

3.4 、controller代码逻辑

public class LoginController : Controller    {        // 登录页面        public IActionResult LoginView()        {            return View();        }        /// <summary>        /// 登录方法        /// </summary>        /// <returns></returns>        [AllowAnonymous]        public async Task<IActionResult> Login()        {            var claims = new List<Claim>            {                new Claim(ClaimTypes.Name,"xiaohemiao"),                new Claim(ClaimTypes.Role,"Admin"),                new Claim(ClaimTypes.Expired,DateTime.Now.AddMinutes(1).ToString("yyyy-MM-dd HH:mm:ss"))                            };            var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme                , new ClaimsPrincipal(claimsIdentity)                , new AuthenticationProperties()                {                                    });                        return Redirect("/Login/Index");        }        /// <summary>        /// 登录成功之后跳转的页面        /// </summary>        /// <returns></returns>        [Authorize(Policy = "RolePolicy")]        public IActionResult Index()        {            return View();        }        /// <summary>        /// 登出        /// </summary>        /// <returns></returns>        public async Task<IActionResult> LoginOff()        {            await HttpContext.SignOutAsync();            return Redirect("/Login/LoginView");        }        /// <summary>        /// 无权限页面        /// </summary>        /// <returns></returns>        public IActionResult AccessDenied()        {            return View();        }            }

 

三、简单页面呈现效果

1、登录页面

 

 

2、登录成功跳转的页面

 

 

3、无权限页面

 

posted @ 2022-02-27 00:42 SportSky 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员