身份验证过滤器:如何使用消息执行 HTTP 401
authentication filter: How to do a HTTP 401 with message
我按照 http://bitoftech.net/2014/12/15/secure-asp-net-web-api-using-api-key-authentication-hmac-authentication/ 做了一个自定义身份验证过滤器。
一切正常,但我无法让服务器对 401 说任何话。它正确地给出了 www-authenicate
header 和状态代码 401,但没有 content/body.
我尝试使用 AuthenticationFailureResult
来自 http://www.asp.net/web-api/overview/security/authentication-filters 但没有帮助。我将 AuthenticateAsync
转换为 async
并忽略了 await
警告。
这是我目前的解决方法,评论中的代码是我希望我能做的,主要是让它使用任何格式化程序
//request.CreateResponse(HttpStatusCode.Unauthorized, new { Error = true, Message = "Token is invalid" });
HttpContext.Current.Response.ContentType = "application/json";
HttpContext.Current.Response.Write("{ \"Error\" = true, \"Message\" = \"Token is invalid\" }");
context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], request);
有两种选择:快速但粗暴,更长但更优雅
一个。直接修改HttpResponse:
HttpContext.Current.Response.StatusCode = 401;
HttpContext.Current.Response.Write("some content");
乙。实施 IHttpActionResult
并在 class:
中设置 HttpResponseMessage
的 Content
属性
public class AuthenticationFailureResult : IHttpActionResult
{
public AuthenticationFailureResult(object jsonContent, HttpRequestMessage request)
{
JsonContent = jsonContent;
Request = request;
}
public HttpRequestMessage Request { get; private set; }
public Object JsonContent { get; private set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Execute());
}
private HttpResponseMessage Execute()
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
response.RequestMessage = Request;
response.Content = new ObjectContent(JsonContent.GetType(), JsonContent, new JsonMediaTypeFormatter());
return response;
}
}
然后你就可以像这样使用它了:
context.ErrorResult = new AuthenticationFailureResult(new { Error = true, Message = "Token is invalid" }, request);
注意:如果您想为 JsonContent
使用匿名类型,请确保 AuthenticationFailureResult
在同一个库中实现。
如果您想在 401 响应中附加一条消息,我认为您应该这样做。这就是我在我的项目中所做的:
public class TokenAuthenticationAttribute : AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
// Do your authentication here
}
protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
{
if (actionContext == null)
{
throw new ArgumentNullException("actionContext", "Null actionContext");
}
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
actionContext.Response.Headers.Add("AuthenticationStatus", "NotAuthorized");
actionContext.Response.ReasonPhrase = "Authentication failed";
// Create your content here (I use Student class as an example)
actionContext.Response.Content = new ObjectContent(
typeof (Student),
new Student("Forte", 23),
new JsonMediaTypeFormatter());
}
}
学生class:
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public Student(string name, int age)
{
Name = name;
Age = age;
}
}
然后,我这样使用它:
[TokenAuthentication]
public class DocumentController : ApiController
{
// Your code here
}
编辑!!!
感谢评论中的 wal
建议,这里是将消息附加到响应的更短方式:
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized,
new {Error = true, Message = "Token is invalid"});
那么,您的回复信息将是:
{"$id":"1","error":true,"message":"Token is invalid"}
通过这种方式,您不必再设置 actionContext.Response.Content
。
我按照 http://bitoftech.net/2014/12/15/secure-asp-net-web-api-using-api-key-authentication-hmac-authentication/ 做了一个自定义身份验证过滤器。
一切正常,但我无法让服务器对 401 说任何话。它正确地给出了 www-authenicate
header 和状态代码 401,但没有 content/body.
我尝试使用 AuthenticationFailureResult
来自 http://www.asp.net/web-api/overview/security/authentication-filters 但没有帮助。我将 AuthenticateAsync
转换为 async
并忽略了 await
警告。
这是我目前的解决方法,评论中的代码是我希望我能做的,主要是让它使用任何格式化程序
//request.CreateResponse(HttpStatusCode.Unauthorized, new { Error = true, Message = "Token is invalid" });
HttpContext.Current.Response.ContentType = "application/json";
HttpContext.Current.Response.Write("{ \"Error\" = true, \"Message\" = \"Token is invalid\" }");
context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], request);
有两种选择:快速但粗暴,更长但更优雅
一个。直接修改HttpResponse:
HttpContext.Current.Response.StatusCode = 401;
HttpContext.Current.Response.Write("some content");
乙。实施 IHttpActionResult
并在 class:
HttpResponseMessage
的 Content
属性
public class AuthenticationFailureResult : IHttpActionResult
{
public AuthenticationFailureResult(object jsonContent, HttpRequestMessage request)
{
JsonContent = jsonContent;
Request = request;
}
public HttpRequestMessage Request { get; private set; }
public Object JsonContent { get; private set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(Execute());
}
private HttpResponseMessage Execute()
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
response.RequestMessage = Request;
response.Content = new ObjectContent(JsonContent.GetType(), JsonContent, new JsonMediaTypeFormatter());
return response;
}
}
然后你就可以像这样使用它了:
context.ErrorResult = new AuthenticationFailureResult(new { Error = true, Message = "Token is invalid" }, request);
注意:如果您想为 JsonContent
使用匿名类型,请确保 AuthenticationFailureResult
在同一个库中实现。
如果您想在 401 响应中附加一条消息,我认为您应该这样做。这就是我在我的项目中所做的:
public class TokenAuthenticationAttribute : AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
// Do your authentication here
}
protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
{
if (actionContext == null)
{
throw new ArgumentNullException("actionContext", "Null actionContext");
}
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
actionContext.Response.Headers.Add("AuthenticationStatus", "NotAuthorized");
actionContext.Response.ReasonPhrase = "Authentication failed";
// Create your content here (I use Student class as an example)
actionContext.Response.Content = new ObjectContent(
typeof (Student),
new Student("Forte", 23),
new JsonMediaTypeFormatter());
}
}
学生class:
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public Student(string name, int age)
{
Name = name;
Age = age;
}
}
然后,我这样使用它:
[TokenAuthentication]
public class DocumentController : ApiController
{
// Your code here
}
编辑!!!
感谢评论中的 wal
建议,这里是将消息附加到响应的更短方式:
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized,
new {Error = true, Message = "Token is invalid"});
那么,您的回复信息将是:
{"$id":"1","error":true,"message":"Token is invalid"}
通过这种方式,您不必再设置 actionContext.Response.Content
。