ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

.Net Core AOP之AuthorizeAttribute

2022-02-27 01:01:08  阅读:201  来源: 互联网

标签:Core return AuthorizeAttribute app options Login new Net public


一、简介

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

 

标签:Core,return,AuthorizeAttribute,app,options,Login,new,Net,public
来源: https://www.cnblogs.com/sportsky/p/15940483.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有