首页 > 其他分享 >.Net Core AOP之AuthorizeAttribute

.Net Core AOP之AuthorizeAttribute

时间:2023-11-07 09:13:29浏览次数:37  
标签: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、无权限页面

 

 

  来自:https://www.cnblogs.com/sportsky/p/15940483.html

标签:Core,return,AuthorizeAttribute,app,options,Login,new,Net,public
From: https://www.cnblogs.com/djd66/p/17814258.html

相关文章

  • .Net Core之JWT授权
    一、什么是JWT文章参考:https://www.leo96.com/article/detail/55JSONWeb令牌(JWT)是一个开放标准(RFC7519),它定义 了一种紧凑且自包含的方式,用于在各方之间安全地传输信息作为JSON对象。由于此信息是经过数字签名的,因此可以被验证和信任。可以使用秘密(使用HMAC算法)或使用RSA或EC......
  • .NET(C#) Linq Concat和Union以及Select和SelectMany的使用及区别
    1、Concat操作符Concat操作符用于连接两个序列,生成一个新序列。usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceConsoleApplication{classProgram{staticvoidMain(s......
  • .NET C# 9.0 record和with的定义及使用
    C#9引入record,它一种可以创建的新引用类型,而不是类或结构。C#10添加了recordstructs,以便可以将记录定义为值类型。记录与类不同,区别在于record类型使用基于值的相等性。两个记录类型的变量在它们的类型和值都相同时,它们是相等的。with表达式在C#9.0及更高版本中可用,......
  • .NET(C#) LinkedList、Queue<T>和Stack<T>的使用
    本文主要介绍.NET(C#)中,LinkedList链表、Queue<T>队列和Stack<T>堆栈的使用,以及相关的示例代码。1、LinkedList(链表)链表中元素存储内存中是不连续分配,每个元素都有记录前后节点,节点值可以重复,不能通过下标访问,泛型的使用保证类型安全,可以避免装箱拆箱,找元素就只能遍历,查找不方......
  • .NET(C#) Linq GroupBy和GroupJoin的使用
    Linq是LanguageIntegratedQuery的简称,它是微软在.NETFramework3.5里面新加入的特性,用以简化查询查询操作。本文主要介绍.NET(C#)中Linq的GroupBy和GroupJoin操作符1、GroupBy操作符GroupBy操作符类似于SQL语言仲的GruopBy语句,这里的GroupBy操作符用于将输入序列中的元素进......
  • .NET(C#) Cast和OfType的使用
    Linq是LanguageIntegratedQuery的简称,它是微软在.NETFramework3.5里面新加入的特性,用以简化查询查询操作。本文主要介绍.NET(C#)中Linq的Cast和OfType操作符。1、Cast操作符Cast操作符用于将一个类型为IEnumerable的集合对象转换为IEnumerable<T>类型的集合对象。也就是非......
  • .NET(C#) Linq Range和Repeat的使用
    Linq是LanguageIntegratedQuery的简称,它是微软在.NETFramework3.5里面新加入的特性,用以简化查询查询操作。本文主要介绍.NET(C#)中Linq的Range和Repeat操作符。1、Range操作符Range操作符用于辅助生成一个整数序列。usingSystem;usingSystem.Collections.Generic;usi......
  • .NET(C#) 对象的拷贝(浅拷贝和深拷贝)
    本文主要介绍.NET(C#),对象的拷贝,包括浅拷贝和深拷贝,以及浅拷贝和深拷贝的实现方式,不同的实现方式之间的性能对比。1、浅拷贝和深拷贝浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用型字段则指复制它的一个引用到目标对象。如果改变目标对象中引用型字段的值......
  • NET(C#) Linq Take和TakeWhile的使用
    Linq是LanguageIntegratedQuery的简称,它是微软在.NETFramework3.5里面新加入的特性,用以简化查询查询操作。本文主要介绍.NET(C#)中Linq的Take和TakeWhile操作符。1、Take操作符Take操作符用于从输入序列中返回指定数量的元素,常用于分页。usingSystem;usingSystem.Coll......
  • 在ASP.NET MVC框架中,如何处理多个提交按钮?
    内容来自DOChttps://q.houxu6.top/?s=在ASP.NETMVC框架中,如何处理多个提交按钮?在ASP.NETFrameworkBeta中,有几种方法可以处理同一表单中的多个提交按钮。一种方法是使用一个隐藏字段来区分不同的提交按钮。例如:<%Html.BeginForm("MyAction","MyController",FormMethod......