• .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、无权限页面

  • 相关阅读:
    html表格,table标签
    2-3VRP的基本配置
    6 sys模块
    3 datetime模块
    2 time模块
    1 模块和包的介绍
    12 函数进阶---生成器
    13 函数进阶---迭代器
    10 函数进阶---闭包
    11 函数进阶---装饰器
  • 原文地址:https://www.cnblogs.com/sportsky/p/15940483.html
Copyright © 2020-2023  润新知