.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、无权限页面
.Net Core AOP之AuthorizeAttribute的更多相关文章
- Asp.net Core AOP实现(采用Autofac)
引用正确的库来实现AOP 新的.NET Core是基于.NET Standard的..所以我们在引用库的时候特别要注意相关的兼容问题. 在传统的ASP.NET中,使用过Autofac来进行AOP操作的 ...
- .Net Core Aop之IResourceFilter
一.简介 在.net core 中Filter分为一下六大类: 1.AuthorizeAttribute(权限验证) 2.IResourceFilter(资源缓存) 3.IActionFilter(执 ...
- .Net Core Aop之IActionFilter
一.简介 在.net core 中Filter分为以下六大类: 1.AuthorizeAttribute(权限验证) 2.IResourceFilter(资源缓存) 3.IActionFilter(执 ...
- .Net Core AOP之IResultFilter
一.简介 在.net core 中Filter分为以下六大类: 1.AuthorizeAttribute(权限验证) 2.IResourceFilter(资源缓存) 3.IActionFilter(执 ...
- .Net Core AOP之IExceptionFilter
一.简介 在.net core 中Filter分为以下六大类: 1.AuthorizeAttribute(权限验证) 2.IResourceFilter(资源缓存) 3.IActionFilter(执 ...
- .net core AOP之Filter
当我们进行项目开发时,往往在开发过程中需要临时加入一些常用功能性代码,如身份验证.日志记录.异常获取等功能.如果每个方法中都加入这些功能性代码的话,无疑使项目显得过于臃肿,代码繁杂.这时候就要加入过滤 ...
- ASP.NET Core 认证与授权[5]:初识授权
经过前面几章的姗姗学步,我们了解了在 ASP.NET Core 中是如何认证的,终于来到了授权阶段.在认证阶段我们通过用户令牌获取到用户的Claims,而授权便是对这些的Claims的验证,如:是否拥 ...
- 面向复杂应用,Node.js中的IoC容器 -- Rockerjs/core
Rockerjs Core 项目地址 项目主页 基于 TypeScript 和注解的轻量级IoC容器,提供了依赖注入.面向切面编程及异常处理等功能.Rockerjs Core可在任意工程中引入,是一个 ...
- Spring AOP 中 advice 的四种类型 before after throwing advice around
spring AOP(Aspect-oriented programming) 是用于切面编程,简单的来说:AOP相当于一个拦截器,去拦截一些处理,例如:当一个方法执行的时候,Spring 能够拦截 ...
随机推荐
- STC8H开发(六): SPI驱动ADXL345三轴加速度检测模块
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- 刷机错误ERROR:STATUS_BROM_CMD__FAIL
ERROR:STATUS_BROM_CMD_STARTCMD_FAIL window驱动没有安装好,几乎所有安装包都有问题,很难成功,成功了也很慢.这是因为之前检测到且烧写错误,然后上一次的驱动错误连 ...
- MySql服务器逻辑架构
一.MySql服务器逻辑架构图 每个虚线框都是一层: 第一层:最上层的服务器不是MySql所独有的,大多数基于网络的客户端/服务器工具或者服务都有类似的系统.比如链接处理,授权认证,安 ...
- 定位new
常规的new是分配内存,然后调用相应的构造函数,而定位new是在已经分配内存的上面调用构造函数: // ConsoleApplication7.cpp : 定义控制台应用程序的入口点. #includ ...
- java继承子类实例化过程(细节解释)
1 package face_08; 2 class Fu{ 3 Fu(){ 4 super(); 5 show(); 6 return; 7 } 8 void show() { 9 System.o ...
- python网络爬虫-动态网页抓取(五)
动态抓取的实例 在开始爬虫之前,我们需要了解一下Ajax(异步请求).它的价值在于在与后台进行少量的数据交换就可以使网页实现异步更新. 如果使用Ajax加载的动态网页抓取,有两种方法: 通过浏览器审查 ...
- Django class meta
class Main(models.Model): img = models.CharField(max_length=200) # 图片 name = models.CharField(max_le ...
- window-server 服务器解决远程连接
mstsc 连接远程服务器,出现黑屏的情况: 解决方案: 运行 -> 输入gpedit.msc,进入组策略 -> 计算机配置 -> 管理模板 -> Windows组件 -> ...
- Vue+webpack配置实现多页面应用开发
为什么要配置多页面开发? · 由于单页面应用不利于SEO,对于某些资讯类网站不够友好,而多页面则能够更优的解决此问题. · 传统的多页面开发模式(如java的jsp等) 前后端耦合性大,开发效率低,代 ...
- maven项目 子父级工程。
一 .什么是 maven 子父级工程? 建立一个maven项目,然后在该项目 下创建一个module,子级的maven,他继承于父级项目. 1.新建立 maven项目,file ------new- ...