您有一个Web API,并且想要实现自己的授权逻辑,该怎么做?您需要做四件事。
1. 创建您的自定义授权属性
2. 在控制器上使用自定义授权属性
3. 在自定义请求管道中间件中创建授权逻辑
4. 启动时注册中间件
创建您的自定义授权属性
1 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] 2 public class CustomAuthorizeAttribute : Attribute 3 { 4 public string[] AllowedUserRoles { get; private set; } 5 6 public CustomAuthorizeAttribute(params string[] allowedUserRoles) 7 { 8 this.AllowedUserRoles = allowedUserRoles; 9 } 10 }
在控制器上使用自定义授权属性
1 [ApiController] 2 [Route("[controller]")] 3 public class WeatherForecastController : ControllerBase 4 { 5 6 [HttpGet] 7 [CustomAuthorize("Admin", "Supervisor", "Worker")] 8 public string Get() 9 { 10 return "Sunny"; 11 } 12 }
在自定义请求管道中间件中创建授权逻辑
1 public static class CustomAuthorizationMiddleware 2 { 3 public static async Task Authorize(HttpContext httpContext, Func next) 4 { 5 var endpointMetaData = httpContext.GetEndpoint().Metadata; 6 7 bool hasCustomAuthorizeAttribute = endpointMetaData.Any(x => x is CustomAuthorizeAttribute); 8 9 if (!hasCustomAuthorizeAttribute) 10 { 11 await next.Invoke(); 12 return; 13 } 14 15 CustomAuthorizeAttribute customAuthorizeAttribute = endpointMetaData 16 .FirstOrDefault(x => x is CustomAuthorizeAttribute) as CustomAuthorizeAttribute; 17 18 // TODO: change authorization logic 19 bool isAuthorized = customAuthorizeAttribute.AllowedUserRoles 20 .Any(allowedRole => httpContext.User.IsInRole(allowedRole)); 21 22 if (isAuthorized) 23 { 24 await next.Invoke(); 25 return; 26 } 27 28 httpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; 29 await httpContext.Response.WriteAsync("unauthorized"); 30 } 31 }
启动时注册中间件
1 public class Startup 2 { 3 public Startup(IConfiguration configuration) 4 { 5 Configuration = configuration; 6 } 7 8 public IConfiguration Configuration { get; } 9 10 // This method gets called by the runtime. Use this method to add services to the container. 11 public void ConfigureServices(IServiceCollection services) 12 { 13 services.AddControllers(); 14 } 15 16 // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 17 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 18 { 19 if (env.IsDevelopment()) 20 { 21 app.UseDeveloperExceptionPage(); 22 } 23 24 app.UseHttpsRedirection(); 25 26 app.UseRouting(); 27 28 app.Use(CustomAuthorizationMiddleware.Authorize); 29 30 app.UseEndpoints(endpoints => 31 { 32 endpoints.MapControllers(); 33 }); 34 } 35 }
确保在调用app.UseRouting()之后添加中间件。这样可以确保在将路由 信息添加到HttpContext 后执行您的中间件。