【发布时间】:2014-10-21 13:42:11
【问题描述】:
我的问题如下。
客户端通过 Web 界面 (HTTP) 与我的 WCF 服务进行交互。 某些服务操作需要客户端通过提供用户名和密码进行身份验证。 为简单起见,我们假设这些信息是通过查询字符串参数(或在 HTTP 基本身份验证中的 Authorization 标头中)传递的。
例如,可以通过http://myhost.com/myservice/myop?user=xxx&password=yyy调用服务操作
由于多个服务操作需要这种类型的身份验证,我想将身份验证代码排除在单个操作之外。
通过环顾四周,我了解了服务行为并想出了以下代码:
public class MyAuthBehaviorAttribute : Attribute, IServiceBehavior, IDispatchMessageInspector {
/********************/
/* IServiceBehavior */
public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
System.ServiceModel.ServiceHostBase serviceHostBase) {
// It’s called right after the runtime was initialized
foreach (ChannelDispatcher chDisp in serviceHostBase.ChannelDispatchers) {
foreach (EndpointDispatcher epDisp in chDisp.Endpoints) {
epDisp.DispatchRuntime.MessageInspectors.Add(new MyAuthBehaviorAttribute());
}
}
}
/*...*/
/*****************************/
/* IDispatchMessageInspector */
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request,
System.ServiceModel.IClientChannel channel,
System.ServiceModel.InstanceContext instanceContext) {
object correlationState = null;
var prop = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
var parts = HttpUtility.ParseQueryString(prop.QueryString);
string user = parts["user"];
string password = parts["password"];
if (AuthenticateUser(user,password)) {
// ???????????????????????????
}
else {
throw new Exception("...");
}
return correlationState;
}
/*...*/
}
然后,通过注解服务
[MyAuthBehavior]
public class Service : IContract
{
// implementation of the IContract interface
}
现在,我设法在任何服务操作之前执行我的行为。 但是,我有以下问题:
- 如何将身份验证结果传递给服务操作?
- 如何将身份验证限制为仅几个服务操作?
关于最后一点,我查看了 IOperationBehavior,但在这种情况下,我可以只附加 IParameterInspectors 而不是 IDispatchMessageInspectors。这是不可取的,因为我可能需要查看消息标头,例如,如果我决定在支持 HTTP 基本身份验证时考虑 Authorization HTTP 标头。
作为一个相关问题,我还想问一下您对我的方法的看法,以及是否有更好(不过分复杂)的方法。
【问题讨论】:
标签: c# web-services wcf authentication