问题
Background:
I want to authenticate a POST request to my web API using an implementation of IAuthenticationFilter
injected using Ninject. To authenticate a request I need access to request body.
Problem:
ActionContext.ActionArguments
, which I usually use to access request payload, is empty when I try to access it inside the filter.
Question:
- How to access POST request payload inside an
IAuthenticationFilter
implementation? - Why
ActionContext.ActionArguments
is empty inside anIAuthenticationFilter
implementation, but has values if my filter implementsActionFilterAttribute
?
Code:
Filter implementation:
public class AuthenticateFilter : IAuthenticationFilter
{
private const string AuthenticationHeader = "X-Auth-Token";
private const string UserHeader = "X-Auth-User";
private readonly ILog log;
public AuthenticateFilter(ILog log)
{
this.log = log;
}
public Task AuthenticateAsync(HttpAuthenticationContext context,
CancellationToken cancellationToken)
{
// context.ActionContext.ActionArguments is empty
if (!IsAuthenticated(context))
{
context.ErrorResult =
new StatusCodeResult(HttpStatusCode.Unauthorized,
context.Request);
}
return Task.FromResult(0);
}
public Task ChallengeAsync(HttpAuthenticationChallengeContext context,
CancellationToken cancellationToken)
{
context.Result =
new StatusCodeResult(HttpStatusCode.Unauthorized,
context.Request);
return Task.FromResult(0);
}
private bool IsAuthenticated(HttpAuthenticationContext context)
{
// Authentication code here
// context.ActionContext.ActionArguments is empty
}
}
The filter is injected using Ninject when controller method has a attribute.
kernel.BindHttpFilter<AuthenticateFilter>(FilterScope.Action)
.WhenActionMethodHas<AuthenticateAttribute>();
AuthenticateAttribute
is an empty ActionFilterAttribute
.
public class AuthenticateAttribute : ActionFilterAttribute
{
}
Thank you!
回答1:
This is expected behavior. Authentication
and Authorization
filters run before ModelBinding/Formatter deserialization stage, where as Action
filters run after this stage.
回答2:
I struggled a bit myself with the same situation, in case it helps anyone, you need to use Reflection and System.Web.Helpers's Json.Decode:
public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
HttpRequestMessage request = context.Request;
var content = request.Content.ReadAsAsync(typeof(Object)).Result.ToString();
var methodInfo = ((ReflectedHttpActionDescriptor)request.Properties["MS_HttpActionDescriptor"]).MethodInfo; // get the method descriptor
if (methodInfo.GetParameters().Any()) //this will get the parameter types
{
var parameterType = methodInfo.GetParameters().First().ParameterType; //you iterate can through the parameters if you need
var casted = Json.Decode(content, parameterType); //convert the json content into the previous type (your parameter)
//do something with your populated object :)
}
return Task.FromResult(context.Request);
}
来源:https://stackoverflow.com/questions/24493425/actioncontext-actionarguments-is-empty-in-iauthenticationfilter