我现在用的是Asp.Net的Web API。 我希望能够筛选出基于连接的客户端访问权限的响应对象的某些字段。
例:
class Foo
{
[AccessFilter("Uberlord")]
string Wibble { get; set; }
string Wobble { get; set; }
}
当返回数据的归档Wibble
只应返回如果当前用户的上下文能够满足“Uberlord”的价值。
有三种途径,我探索,但我还没有得到一个有效的解决方案:
- 自定义的WebAPI MediaTypeFormatter。
- 自定义json.net IContractResolver。
- 某种AOP包装的用于控制器操纵响应对象
我的这些问题是:
- 自定义格式不觉得这样做合适的位置,但可能是唯一的选择。
- 自定义JSON序列将不能访问当前上下文,所以我将不得不工作了这一点。
- 与前两个选项,你就需要对每个响应格式,JSON,XML,一些自定义格式的具体实现,等等。这意味着,如果支持的另一种响应类型则需要自定义格式/串,以防止敏感数据泄露。
- 该AOP控制器的包装将需要大量的反思。
一个额外的奖励。将剥离出使用相同的机制的入站请求对象从所述字段的值。
我错过了一个明显的钩? 这已经通过另一种方式来解决?
它实际上是简单了很多,比我第一个念头。 我没有意识到的是, DelegatingHandler
可以用来处理响应以及在请求网络API管线 。
一个ASP.NET Web API消息的生命周期
委派处理程序
委托处理程序是在消息管道的扩展点,让您可以将它传递给管道的其余部分之前按摩请求。 的道路上的响应消息发送回具有穿过委派处理程序为好,这样任何响应也可以被监视/过滤/在该可扩展性点更新。
如果需要委派处理程序,可以绕过管道的其余部分也和回送和HTTP响应自己。
例
这里是一个DelegatingHandler其可以操纵响应对象或完全替换它的示例性实现。
public class ResponseDataFilterHandler : DelegatingHandler
{
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken)
.ContinueWith(task =>
{
var response = task.Result;
//Manipulate content here
var content = response.Content as ObjectContent;
if (content != null && content.Value != null)
{
((SomeObject)content.Value).SomeProperty = null;
}
//Or replace the content
response.Content = new ObjectContent(typeof(object), new object(), new JsonMediaTypeFormatter());
return response;
});
}
}
我在作品中类似的问题在这里: ASP.NET的WebAPI条件系列化基于用户角色
我想出了一个建议的解决方案是让我ApiController继承从BaseApiController将覆盖Initalize功能设置根据用户的角色相应的格式。 我还没有决定我是否会走这条路还没有,但也许它会为你工作。
protected override void Initialize(System.Web.Http.Controllers.HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
// If the user is in a sensitive-data access role
controllerContext.Configuration.Formatters.Add(/*My Formatter*/);
// Otherwise use the default ones added in global app_start that defaults to remove sensitive data
}