ResultFilter
在视图渲染之前或者之后执行的操作
1.新建一个CustomResultFilterAttribute类,实现IResultFilter接口
public class CustomResultFilterAttribute : Attribute, IResultFilter
{
/// <summary>
/// 渲染视图之前执行
/// </summary>
/// <param name="context"></param>
public void OnResultExecuting(ResultExecutingContext context)
{
Console.WriteLine("渲染视图之前执行");
}
/// <summary>
/// 渲染视图之后执行
/// </summary>
/// <param name="context"></param>
public void OnResultExecuted(ResultExecutedContext context)
{
Console.WriteLine("渲染视图之后执行");
}
}
2.应用
[CustomResultFilterAttribute]
public IActionResult IndexResult()
{
return View();
}
结果
ResultFilter的应用
语言的切换,其实就需要两个视图;要根据语言的不同,来选择不同的视图来渲染;
1.CustomResultFilterAttribute.cs
public class CustomResultFilterAttribute : Attribute, IResultFilter
{
private IModelMetadataProvider _modelMetadataProvider = null;
public CustomResultFilterAttribute(IModelMetadataProvider modelMetadataProvider)
{
_modelMetadataProvider = modelMetadataProvider;
}
/// <summary>
/// 渲染视图之前执行
/// </summary>
/// <param name="context"></param>
public void OnResultExecuting(ResultExecutingContext context)
{
Console.WriteLine("渲染视图之前执行");
//在这里就可以有一个判断,符合某个情况,就使用哪一个视图;
string view = context.HttpContext.Request.Query["view"];//可以是配置文件
if (view == "1")//中文
{
var result = new ViewResult { ViewName = "~/Views/ActionF/IndexResult.cshtml" };
result.ViewData = new ViewDataDictionary(_modelMetadataProvider,context.ModelState);
context.Result = result;
}
else
{
var result = new ViewResult { ViewName = "~/Views/ActionF/IndexResult_2.cshtml" };
result.ViewData = new ViewDataDictionary(_modelMetadataProvider, context.ModelState);
context.Result = result;
}
}
/// <summary>
/// 渲染视图之后执行
/// </summary>
/// <param name="context"></param>
public void OnResultExecuted(ResultExecutedContext context)
{
Console.WriteLine("渲染视图之后执行");
}
2.使用
//[CustomResultFilterAttribute]
[TypeFilter(typeof(CustomResultFilterAttribute))]
public IActionResult IndexResult()
{
return View();
}
鉴权授权
为了拦截一些操作:
传统的授权方式: session/Cookies来完成
.Net5鉴权授权
通过中间件来支持;
1.startup.cs中 Configure方法
在app.UseRouting();之后,在app.UseEndpoints() 之前,增加鉴权授权:
鉴权: app.UseAuthenticaton0;-----------检测用户是否登录
授权: app.UseAuthorization();:----------授权检测有没有权限,是否能够访问后续的页面功能
2.在ConfigureServices中增加
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(option=>
{
option.LoginPath = new PathString("/Home/Login");//如果授权失败,就跳转到这个路径
});
3.指定哪些Action需要做鉴权授权
标记特性:也可以标记在控制器,全局;
[Microsoft.AspNetCore.Authorization.Authorize]
4.当Authorize标记为控制器、全局,可以使用匿名(自定义)避开权限检查 [AllowAnonymousAttribute]
登录Demo
1.
2.
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(option=>
{
option.LoginPath = new PathString("/Home/Login");//如果授权失败,就跳转到这个路径
});
3.编写一个简易的登录页面Login.cshtml
@{
ViewData["Login"] = "login Page";
}
<div>
<h1>Login</h1>
<div style="color:orangered;">@ViewBag.Msg </div>
<div>
<form action="/Home/Login" method="post">
<input type="text" name="name" />
<br />
<input type="text" name="password" />
<br />
<input type="submit" value="提交"/>
</form>
</div>
</div>
4.Controller
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
[Authorize]
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
public IActionResult Login()
{
return View();
}
[HttpPost]
public IActionResult Login(string name,string password)
{
//string verifyCode = base.HttpContext.Session.GetString("CheckCode");
//if (verifyCode != null && verifyCode.Equals(verify,
// StringComparison.CurrentCultureIgnoreCase))
//{
//}
if ("123".Equals(name) && "123".Equals(password))
{
#region 鉴权:鉴权,检测有没有登录,登录的是谁,赋值给User
//rolelist 是登录成功后用户的角色---是来自于数据库的查询;不同的用户会查询出不同的角色;
var rolelist = new List<string>() {
"Admin",
"Teacher",
"Student"
};
//ClaimTypes.Role就是做权限认证的标识;
var claims = new List<Claim>()//鉴别你是谁,相关信息
{
new Claim(ClaimTypes.Role,"Admin"),
new Claim(ClaimTypes.Name,name),
new Claim("password",password),//可以写入任意数据
new Claim("Account","Administrator"),
new Claim("role","admin"),
new Claim("admin","admin"),
};
foreach (var role in rolelist)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
//将用户放在ClaimsPrincipal里面去了;相当身份证,将信息写到身份证里面去;
ClaimsPrincipal userPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Customer"));
HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, userPrincipal, new AuthenticationProperties
{
ExpiresUtc = DateTime.UtcNow.AddMinutes(30),//过期时间:30分钟
}).Wait();
#endregion
var user = HttpContext.User;
return base.Redirect("/Home/Privacy");//成功后跳转页面
}
else
{
base.ViewBag.Msg = "账号或者密码错误";
}
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
.NET5鉴权授权--角色授权(角色写死了)
不同的用户,可能会存在不同的角色,不同的角色,可能在访问不同的页面的时候,需要做不同拦截;
角色授权其实就是通过角色不同,做不同的权限拦截;
1.标记的时候,通过逗号分隔不同的角色---只要是有一个角色符合就能够访问,角色之间是或者的关系
[Authorize(Roles = "Admin,Teacher,Student")]
2.多个特性标记--多个角色之间是且的关系,必须要包含所有的角色,才能够访问
[Authorize(Roles = "Admin")]
[Authorize(Roles = "Teacher")]
[Authorize(Roles = "Student")]
应用实例
1.
2.
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(option=>
{
option.LoginPath = new PathString("/Home/Login");//如果授权失败,就跳转到这个路径
});
3.Controller
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
}
//标记的时候,通过逗号分隔不同的角色---只要是有一个角色符合就能够访问,角色之间是或者的关系
[Authorize(Roles = "Admin,Teacher,Student")]
public IActionResult IndexOne()
{
return View();
}
/// <summary>
/// 多个特性标记--多个角色之间是且的关系,必须要包含所有的角色,才能够访问
/// </summary>
/// <returns></returns>
[Authorize(Roles = "Admin")]
[Authorize(Roles = "Teacher")]
[Authorize(Roles = "Student")]
public IActionResult IndexTwo()
{
return View();
}
/// <summary>
/// 多个特性标记--多个角色之间是且的关系,必须要包含所有的角色,才能够访问
/// </summary>
/// <returns></returns>
[Authorize(Roles = "fellow")]
[Authorize(Roles = "Teacher")]
public IActionResult Privacy()
{
return View();
}
[AllowAnonymousAttribute]
public IActionResult Login()
{
return View();
}
[HttpPost]
[AllowAnonymousAttribute]//匿名--避开权限检查
public IActionResult Login(string name,string password)
{
//string verifyCode = base.HttpContext.Session.GetString("CheckCode");
//if (verifyCode != null && verifyCode.Equals(verify,
// StringComparison.CurrentCultureIgnoreCase))
//{
//}
if ("123".Equals(name) && "123".Equals(password))
{
//登录成功后,此用户对应有多少角色,就能够查询出来
#region 鉴权:鉴权,检测有没有登录,登录的是谁,赋值给User
//rolelist 是登录成功后用户的角色---是来自于数据库的查询;不同的用户会查询出不同的角色;
var rolelist = new List<string>() {
"Admin",
"Teacher",
"Student"
};
//ClaimTypes.Role就是做权限认证的标识;
var claims = new List<Claim>()//鉴别你是谁,相关信息
{
new Claim(ClaimTypes.Role,"Admin"),
new Claim(ClaimTypes.Name,name),
new Claim("password",password),//可以写入任意数据
new Claim("Account","Administrator"),
new Claim("role","admin"),
new Claim("admin","admin"),
};
foreach (var role in rolelist)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
//将用户放在ClaimsPrincipal里面去了;相当身份证,将信息写到身份证里面去;
ClaimsPrincipal userPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "Customer"));
HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, userPrincipal, new AuthenticationProperties
{
ExpiresUtc = DateTime.UtcNow.AddMinutes(30),//过期时间:30分钟
}).Wait();
#endregion
var user = HttpContext.User;
return base.Redirect("/Home/Privacy");//成功后跳转页面
}
else
{
base.ViewBag.Msg = "账号或者密码错误";
}
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
.NET5鉴权授权----策略鉴权
上面角色授权是在代码中把角色固定死了;如何能够自己来完成校验逻辑?
1.(1)创建一个类为【CustomAuthorizationHandler】,这个类专用来检验逻辑的,要求继承自【AuthorizationHandler<>】泛型类(泛型类中要求实现【IAuthorizationRequirement】接口)然后在CustomAuthorizationHandler类中实现【HandleRequirementAsync】抽象方法,写逻辑。
就是两个类
CustomAuthorizationRequirement.cs
public class CustomAuthorizationRequirement:IAuthorizationRequirement
{
public string Name { get; set; }
public CustomAuthorizationRequirement(string policyName)
{
this.Name = policyName;
}
}
CustomAuthorizationHander.cs
public class CustomAuthorizationHander : AuthorizationHandler<CustomAuthorizationRequirement>
{
public CustomAuthorizationHander()
{
}
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomAuthorizationRequirement requirement)
{
if (requirement.Name == "Policy01")
{
//策略1的逻辑
}
if (requirement.Name == "Policy02")
{
//策略2的逻辑
}
if (requirement.Name == "Policy03")
{
//策略3的逻辑
}
if (true)
{
}
//在这里可以定义自己的规则
{
/*
其实这里可以去数据库里面做一些查询,然后根据用户的信息,做计算:如果符合就context.Succd(requirement)
否则就Task。CompletedTask
*/
}
//context.User 鉴权成功(登录成功后),用户的信息
var role = context.User.FindFirst(u => u.Value.Contains("admin"));
if (role != null)
{
context.Succeed(requirement);//验证通过了
}
return Task.CompletedTask;//验证不通过
}
}
2.让自定义逻辑生效: 在ConfigureServices方法中注册进来
services.AddSingleton<IAuthorizationHandler, CustomAuthorizationHander>();
3.在Startup.cs中ConfigureServices方法中注册支持策略授权,也可以支持多种策略认证。
#region 支持多种策略认证
services.AddAuthorization(options =>
{
options.AddPolicy("customPolicy", policy =>
{
policy.AddRequirements(new CustomAuthorizationRequirement("Policy01"));
});
});
services.AddAuthorization(options =>
{
options.AddPolicy("customPolicy01", policy =>
{
policy.AddRequirements(new CustomAuthorizationRequirement("Policy02"));
});
});
services.AddAuthorization(options =>
{
options.AddPolicy("customPolicy02", policy =>
{
policy.AddRequirements(new CustomAuthorizationRequirement("Policy03"));
});
});
#endregion
4.使用
[Authorize(policy: "customPolicy")]
public IActionResult Privacy()
{
return View();
}