• .net MVC下鉴权认证(二)


    上次讲了.net mvc下鉴权认证的传统方法通过过滤器来实现,那进入.net core时代以后,可以通过鉴权中间件来实现,下面就以mvc程序为例来说明下通过中间件如何来实现。

    这里的环境使用的是vs2019 + .net core3.1

    在startup的ConfigureServices中配置认证

    1. services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    2. .AddCookie(op => {
    3. op.LoginPath = new PathString("/Login");//登录路径
    4. op.AccessDeniedPath = new PathString("/Login/Denied");//无权限地址
    5. });

    然后在Configure中配置中间件,注意要放在app.UseRouting和app.UseEndpoints两者之间才可以

    1. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
    2. if (env.IsDevelopment()) {
    3. app.UseDeveloperExceptionPage();
    4. }
    5. else {
    6. app.UseExceptionHandler("/Home/Error");
    7. }
    8. app.UseStaticFiles();
    9. app.UseRouting();
    10. app.UseAuthentication();//鉴权 是否登录
    11. app.UseAuthorization();//授权 是否有权限访问此操作
    12. app.UseEndpoints(endpoints => {
    13. endpoints.MapControllerRoute(
    14. name: "default",
    15. pattern: "{controller=Home}/{action=Index}/{id?}");
    16. });
    17. }

    然后在要管理权限的控制器或action上进行标记特性[Authorize]就行了,如果不需要进行管理则可以使用[AllowAnonymousAttribute]特性标记就行

    1. public class HomeController : Controller {
    2. private readonly ILogger _logger;
    3. public HomeController(ILogger logger) {
    4. _logger = logger;
    5. }
    6. [Authorize]
    7. public IActionResult Index() {
    8. return View();
    9. }
    10. }

    登陆控制器代码

    1. public class LoginController : Controller {
    2. public IActionResult Index() {
    3. return View();
    4. }
    5. public IActionResult DoLogin(string account, string pwd) {
    6. if (account == "1646" && pwd == "123") {
    7. var roleList = new List<string>() {
    8. "admin",
    9. "test"
    10. };
    11. //身份用户声明
    12. var claims = new List() {
    13. new Claim(ClaimTypes.Name, $"{account}信息"),
    14. new Claim("account", account)
    15. };
    16. //填充角色
    17. foreach (var item in roleList) {
    18. claims.Add(new Claim(ClaimTypes.Role, item));
    19. }
    20. //装载到身份主体中
    21. ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "UserInfo"));
    22. //写入到cookie中
    23. HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal,
    24. new AuthenticationProperties {
    25. ExpiresUtc = DateTime.Now.AddMinutes(30)//设置过期时间
    26. }).Wait();
    27. //跳转
    28. return RedirectToAction("Index", "Home");
    29. }
    30. else {
    31. TempData["error"] = "账号或密码不正确";
    32. return RedirectToAction("Index", "Login");
    33. }
    34. }
    35. public IActionResult Denied() {
    36. return View();
    37. }
    38. }

    然后直接访问Home/Index则会报401直接跳转到Login/Index,因为在startup中有进行配置未登陆处理地址为Login/Index.然后通过登录页面执行登录操作后,再次访问Home/Index就可以成功访问了。

    角色管理

    上面的权限管控只是管控到有登录就ok,如果要进一步进行角色的权限管控我们可以在特性[Authorize(Roles ="admin")] 上面加上roles指定可以授权的角色就行,那么此角色可以访问其他角色就不行了。如果有多个角色可以","分开。也可以写多个特性标记在上面,如下面的代码那么只有admin角色才可以访问。因为上面登录代码中我有加上角色claims.Add(new Claim(ClaimTypes.Role, item));里面包含了admin所以此页面可以访问,如果把这个角色拿掉再来访问此页面就会报403跳转到Login/Denied,因为在startup中有配置无权限的跳转路径。

    1. public class HomeController : Controller {
    2. private readonly ILogger _logger;
    3. public HomeController(ILogger logger) {
    4. _logger = logger;
    5. }
    6. [Authorize(Roles ="admin")]
    7. public IActionResult Index() {
    8. return View();
    9. }
    10. }

    自定义策略授权进阶

    可以发现到目前为止我们的角色这些都是,直接在特性中用代码来写的,这种应该只适合一些小的项目,一般项目中我们还是希望能够后台进行配置的。.net core还支持自定义策略授权

    1.添加CustomAuthorizatinRequirement.cs这个类实现接口IAuthorizationRequirement,这个IAuthorizationRequirement是个空接口,我们直接实现不用写什么代码。

    1. public class CustomAuthorizatinRequirement : IAuthorizationRequirement {
    2. }

    2.添加CustomAuthorizationHandler.cs这个认证处理类,这个类需要实现IAuthorizationRequirement这个接口,不过一般我们都是通过继承AuthorizationHandler泛型抽象类来实现。

    1. public class CustomAuthorizationHandler: AuthorizationHandler<CustomAuthorizatinRequirement> {
    2. private IHttpContextAccessor _httpContext;
    3. public CustomAuthorizationHandler(IHttpContextAccessor httpContext) {
    4. _httpContext = httpContext;
    5. }
    6. protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomAuthorizatinRequirement requirement) {
    7. bool flag=false;
    8. var httpContext = _httpContext.HttpContext;
    9. RouteEndpoint res = context.Resource as RouteEndpoint;
    10. if (res != null) {
    11. if (res.RoutePattern.RequiredValues.Keys.Count() == 2){
    12. var action = res.RoutePattern.RequiredValues.ToList().FirstOrDefault(b => b.Key == "action").Value;
    13. var ctr = res.RoutePattern.RequiredValues.ToList().FirstOrDefault(b => b.Key == "controller").Value;
    14. }
    15. }
    16. var user = context.User.Claims.FirstOrDefault(b => b.Type == "account").Value;
    17. if (user == "1646") {
    18. flag = true;
    19. }
    20. if (flag) {
    21. context.Succeed(requirement);
    22. }
    23. return Task.CompletedTask;
    24. }
    25. }

    3.让自定义策略生效,需要在服务注册services.AddSingleton();还有策略的注册

    1. public void ConfigureServices(IServiceCollection services) {
    2. services.AddControllersWithViews();
    3. services.AddSingleton();
    4. //自定义认证处理的服务注册
    5. services.AddSingleton();
    6. services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    7. .AddCookie(op => {
    8. op.LoginPath = new PathString("/Login");//登录路径
    9. op.AccessDeniedPath = new PathString("/Login/Denied");//无权限地址
    10. });
    11. //策略的注册
    12. services.AddAuthorization(op => {
    13. op.AddPolicy("policy1", p => {
    14. p.AddRequirements(new CustomAuthorizatinRequirement());
    15. });
    16. });
    17. }

    然后在控制器上加上

    1. public class HomeController : Controller {
    2. private readonly ILogger _logger;
    3. public HomeController(ILogger logger) {
    4. _logger = logger;
    5. }
    6. [Authorize(Roles ="admin")]
    7. public IActionResult Index() {
    8. return View();
    9. }
    10. [Authorize(policy: "policy1")]
    11. public IActionResult Index1() {
    12. return View();
    13. }
    14. }

    这样我访问Home/Index1的时候如果未登陆则直接跳转到Login/Index,登陆以后就会通过CustomAuthorizationHandler这个处理类来进行授权判断,这里面的业务逻辑可以自己来实现,里面都可以拿到当前访问的controller和action,以前用户角色等信息,对权限判断都不成问题了。

  • 相关阅读:
    2022年湖北武汉建筑安全员ABC证怎么考 在哪里可以报名 ?
    2023OceanBase年度发布会后,有感
    如何为虚拟机添加磁盘,扩充原有分区的磁盘空间
    一文拿捏分布式协调Redis客服端-Redisson
    PyTorch中grid_sample的使用方法
    2023年09月 Python(六级)真题解析#中国电子学会#全国青少年软件编程等级考试
    线程间通信
    安静的思考
    将时间序列转成图像——短时傅里叶方法 Matlab实现
    李白:你的模型权重很不错,可惜被我没收了
  • 原文地址:https://blog.csdn.net/sammy520/article/details/126088734