【问题标题】:Customizable Authorize attribute in asp.net coreasp.net核心中的可自定义授权属性
【发布时间】:2020-06-09 14:08:27
【问题描述】:

我在 Asp.Net Core 中使用 Jwt Token 身份验证,为了进行身份验证,我使用内置属性[Authorize],我想要做的是让这个属性可定制,意味着我想让这个属性可配置,启用它或禁用身份验证,我可以将设置放在appsetting.json

【问题讨论】:

    标签: asp.net-core asp.net-web-api .net-core


    【解决方案1】:

    根据您的描述,我建议您可以尝试使用基于策略的授权来实现您的要求。

    我建议你可以编写一个自定义 Handler 来比较 appsetting.json 值和路由值。

    如果 appsetting.json 值包含请求的路由值,那么你可以返回 Succeed 来避免 auth。

    更多细节,您可以参考以下代码:

    Appseting.json(DisableAuthController 值)

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning",
          "Microsoft.Hosting.Lifetime": "Information"
        },
        "DisableAuthController": "home,default,account"
      }
    }
    

    创建一个名为:UserResourceHandler 的新类

    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc.Filters;
    using Microsoft.AspNetCore.Routing;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Localization.Internal;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace FormAuthCore
    {
        public class UserResourceHandler : AuthorizationHandler<UserResourceRequirement>
        {
    
            private readonly IConfiguration Configuration;
            private readonly IHttpContextAccessor _httpContextAccessor;
    
            public UserResourceHandler(IConfiguration configuration, IHttpContextAccessor httpContextAccessor)
            {
                Configuration = configuration;
                _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
    
    
            }
    
            protected override async Task HandleRequirementAsync(AuthorizationHandlerContext authHandlerContext, UserResourceRequirement requirement)
            {
    
                var re = Configuration.GetSection("DisableAuthController").Value;
    
                var context = _httpContextAccessor.HttpContext.GetRouteData();
                    var area = (context.Values["area"] as string)?.ToLower();
                    var controller = (context.Values["controller"] as string)?.ToLower();
                    var action = (context.Values["action"] as string)?.ToLower();
    
                    if (re.Contains(controller))
                    {
                        authHandlerContext.Succeed(requirement);
                    }
    
            }
        }
    }
    

    创建一个 UserResourceRequirement 类

    using Microsoft.AspNetCore.Authorization;
    
    namespace FormAuthCore
    {
        public class UserResourceRequirement : IAuthorizationRequirement { }   
    }
    

    在 Startup.cs ConfigureServices 方法中添加以下代码:

          services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();
    
            services.AddAuthorization(options =>
            {
                options.AddPolicy("UserResource", policy => policy.Requirements.Add(new UserResourceRequirement()));
            });
    
            services.AddScoped<IAuthorizationHandler, UserResourceHandler>();
    

    为控制器启用基于策略的授权:

    [Authorize(Policy = "UserResource")]
    public class HomeController : Controller
    

    更新:

    我在startup.cs中添加了token1 jwt token auth

                services.AddAuthentication("Token1")
                    .AddJwtBearer("Token1", options =>
                    {
                        options.TokenValidationParameters = new TokenValidationParameters()
                        {
               ValidateIssuer = true,
               ValidIssuer = "abc",
               ValidateAudience = true,
               ValidAudience = "abc",
               ValidateIssuerSigningKey = true,
               IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")),
           };
           options.Events = new JwtBearerEvents()
           {
               OnMessageReceived = context =>
               {
                   var Token = context.Request.Headers["UserCred1"].ToString();
                   context.Token = Token;
                   return Task.CompletedTask;
               },
           };
       });
    
                services.AddAuthorization(options =>
                {
                    options.AddPolicy("UserResource", policy => policy.Requirements.Add(new UserResourceRequirement()));
                });
    
                services.AddScoped<IAuthorizationHandler, UserResourceHandler>();
    

    然后我可以使用_httpContextAccessor.HttpContext.AuthenticateAsync("Token1").Result 来检查令牌是否有效。

      protected override async Task HandleRequirementAsync(AuthorizationHandlerContext authHandlerContext, UserResourceRequirement requirement)
        {
    
    
            var re = Configuration.GetSection("DisableAuthController").Value;
    
            var context = _httpContextAccessor.HttpContext.GetRouteData();
            var re2 = _httpContextAccessor.HttpContext.AuthenticateAsync("Token1").Result;
    
                var area = (context.Values["area"] as string)?.ToLower();
                var controller = (context.Values["controller"] as string)?.ToLower();
                var action = (context.Values["action"] as string)?.ToLower();
    
                if (re.Contains(controller) || re2.Succeeded)
                {
                    authHandlerContext.Succeed(requirement);
                }
    
    
    
        }
    

    【讨论】:

    • 好的,我明白你的意思了,我更关心这个处理程序应该检查生成的 jwt 令牌是否有效我怎样才能做到这一点? @Brando Zhand
    • 您可以使用`_httpContextAccessor.HttpContext.AuthenticateAsync("authenticationSchemename").Result;`来检查jwt令牌是否有效。细节,你可以看到我的更新答案。
    • 这也会检查令牌是否过期?
    • 还有一件事我收到此错误 No SecurityTokenValidator available for token: Bearer : @Brando Zhang
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-02
    • 2020-04-11
    • 2012-05-09
    • 1970-01-01
    • 2021-01-12
    • 2011-07-01
    相关资源
    最近更新 更多