如何在 Controller 上添加 Web API 身份验证过滤器?
How to add Web API authentication filter on Controller?
我实现了web api 2,认证过滤器,基于这个link https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-filters.
过滤器有效,但我无法在控制器上应用?我只能这样全局应用它;
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new MyAuthenticationFilter()); // Global level
MyAuthenticationFilter 实现
using Test1.Web.Areas.Api.Models;
using Test1.Web.Areas.Api.Provisioning;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Filters;
public class MyAuthenticationFilter : IAuthenticationFilter
{
private static CustomerService = new CustomerService();
public bool AllowMultiple => true;
public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
// 1. Look for credentials in the request.
HttpRequestMessage request = context.Request;
AuthenticationHeaderValue authorization = request.Headers.Authorization;
// 2. If there are no credentials, do nothing.
if (authorization == null)
{
this.SetContextErrorResult(context);
return;
}
string apiKey = authorization.Scheme;
// 3. If there are credentials, check Schema exists. Schema has tapiKey value.
// Authorization: apiKey
if (string.IsNullOrWhiteSpace(apiKey))
{
this.SetContextErrorResult(context);
return;
}
// 4. Validate tenant. Here we could use caching
CustomerModel customer = CustomerService.Find(apiKey);
if (customer == null)
{
this.SetContextErrorResult(context);
return;
}
// 5. Credentials ok, set principal
IPrincipal principal = new GenericPrincipal(new GenericIdentity(apiKey), new string[] { });
context.Principal = principal;
return;
}
public async Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
{
// currently we don't need authentication challenge
return;
}
private void SetContextErrorResult(HttpAuthenticationContext context)
{
context.ErrorResult = new AuthenticationFailedResponse();
}
}
public class AuthenticationFailedResponse : IHttpActionResult
{
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Execute());
}
private HttpResponseMessage Execute()
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{
Content = new StringContent(JsonConvert.SerializeObject(new ApiErrorModel()
{
Message = "Authentication failed",
Description = "Missing or incorrect credentials"
}), Encoding.UTF8, "application/json")
};
return response;
}
}
我的一位同事找到了解决方案:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyAuthenticationFilter : FilterAttribute, IAuthenticationFilter
必须将上层代码添加到 MyAuthentication。现在我们可以在 Controller 上使用它了:
[ApiExceptionFilter]
[RoutePrefix("api/provisioning/v0")]
[MyAuthenticationFilter]
public class ProvisioningController : ApiController
首先从 webconfig 中删除以下代码
config.Filters.Add(new MyAuthenticationFilter()); // Global level
然后在控制器上添加属性。首先确保您已经添加了该身份验证过滤器的名称空间。并使用 ActionFilterAttribute 扩展您的 class 并覆盖方法 onactionexcecution。
我实现了web api 2,认证过滤器,基于这个link https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-filters.
过滤器有效,但我无法在控制器上应用?我只能这样全局应用它;
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new MyAuthenticationFilter()); // Global level
MyAuthenticationFilter 实现
using Test1.Web.Areas.Api.Models;
using Test1.Web.Areas.Api.Provisioning;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Filters;
public class MyAuthenticationFilter : IAuthenticationFilter
{
private static CustomerService = new CustomerService();
public bool AllowMultiple => true;
public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
// 1. Look for credentials in the request.
HttpRequestMessage request = context.Request;
AuthenticationHeaderValue authorization = request.Headers.Authorization;
// 2. If there are no credentials, do nothing.
if (authorization == null)
{
this.SetContextErrorResult(context);
return;
}
string apiKey = authorization.Scheme;
// 3. If there are credentials, check Schema exists. Schema has tapiKey value.
// Authorization: apiKey
if (string.IsNullOrWhiteSpace(apiKey))
{
this.SetContextErrorResult(context);
return;
}
// 4. Validate tenant. Here we could use caching
CustomerModel customer = CustomerService.Find(apiKey);
if (customer == null)
{
this.SetContextErrorResult(context);
return;
}
// 5. Credentials ok, set principal
IPrincipal principal = new GenericPrincipal(new GenericIdentity(apiKey), new string[] { });
context.Principal = principal;
return;
}
public async Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
{
// currently we don't need authentication challenge
return;
}
private void SetContextErrorResult(HttpAuthenticationContext context)
{
context.ErrorResult = new AuthenticationFailedResponse();
}
}
public class AuthenticationFailedResponse : IHttpActionResult
{
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Execute());
}
private HttpResponseMessage Execute()
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{
Content = new StringContent(JsonConvert.SerializeObject(new ApiErrorModel()
{
Message = "Authentication failed",
Description = "Missing or incorrect credentials"
}), Encoding.UTF8, "application/json")
};
return response;
}
}
我的一位同事找到了解决方案:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyAuthenticationFilter : FilterAttribute, IAuthenticationFilter
必须将上层代码添加到 MyAuthentication。现在我们可以在 Controller 上使用它了:
[ApiExceptionFilter]
[RoutePrefix("api/provisioning/v0")]
[MyAuthenticationFilter]
public class ProvisioningController : ApiController
首先从 webconfig 中删除以下代码
config.Filters.Add(new MyAuthenticationFilter()); // Global level
然后在控制器上添加属性。首先确保您已经添加了该身份验证过滤器的名称空间。并使用 ActionFilterAttribute 扩展您的 class 并覆盖方法 onactionexcecution。