您应该考虑实施ServiceAuthorizationManager
为您的 WCF 服务实现一个来处理 HTTP Authorization 标头授权。
创建一个继承自 的类System.ServiceModel.ServiceAuthorizationManager
,并覆盖一个或多个CheckAccess
函数以检查传入的 Web 请求并决定是允许还是拒绝它。粗略的草图:
public class MyServiceAuthorizationManager: System.ServiceModel.ServiceAuthorizationManager
{
public override bool CheckAccess(OperationContext operationContext, ref Message message)
{
var reqProp = message.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
var authHeader = reqProp.Headers[HttpRequestHeader.Authorization];
var authorized = // decide if this message is authorized...
if (!authorized)
{
var webContext = new WebOperationContext(operationContext);
webContext.OutgoingResponse.StatusCode = HttpStatusCode.Unauthorized;
webContext.OutgoingResponse.Headers.Add(HttpResponseHeader.WwwAuthenticate, String.Format("Bearer realm=\"{0}\"", baseUri.AbsoluteUri));
}
return authorized;
}
}
将其连接到您创建服务主机的 WCF 服务中:
restAPIServiceHost = new DataServiceHost(typeof(API.RestAPIService), restUris);
var saz = restAPIServiceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
if (saz == null)
{
saz = new ServiceAuthorizationBehavior();
restAPIServiceHost.Description.Behaviors.Add(saz);
}
saz.ServiceAuthorizationManager = new MyServiceAuthorizationManager();
restAPIServiceHost.Open();
这会将授权检查注入到 WCF 服务公开的每个方法中,而无需对服务方法本身进行任何更改。
您的 MyServiceAuthorizationManager 实现也可以使用 web.config 魔术安装到您的 WCF 服务中,但我发现直接代码更易于理解和调试。
请注意,很难在同一服务上使用多个授权检查系统,而不会相互影响或在您的安全范围内留下空白。如果您有UserNamePasswordValidator
强制处理 SOAP 用户凭据的情况,它将拒绝仅包含 HTTP 授权标头的消息。同样,一个ServiceAuthorizationManager
仅检查 HTTP Authorization 标头的 a 将使包含 SOAP 用户凭据的 Web 请求失败。您很可能需要弄清楚如何在同一个身份验证检查中检查这两种身份验证凭据表示。例如,如果消息中不存在 HTTP 授权标头,您可以向上面的 CheckAccess 函数添加代码以查找、提取和测试 SOAP 用户凭据。
当您必须接受多个身份验证表示时,您也需要决定优先级。如果存在 HTTP Authorization 标头,我怀疑它应该优先于 SOAP 消息中包含的任何内容。如果 HTTP 授权标头存在但无效,则句号 - 拒绝未授权的请求。SOAP 中的内容并不重要——无效的 HTTP 授权标头总是坏消息。如果根本没有 HTTP Authorization 标头,那么您可以四处寻找是否存在 SOAP 安全元素,您可以从中获取 SOAP 用户凭据并测试它们的有效性。