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