身份验证WCF REST服务

时间:2011-07-11 10:30:27

标签: wcf authentication rest

我正在使用WebScriptServiceHostFactory构建WCF休息服务以支持POX和Json消息格式,并实现了自定义属性来处理操作的授权。我想将状态代码作为响应发送,并结束对未授权请求的请求,这样我就会在IErrorHandler中从自定义属性和处理中抛出异常。但我无法将状态代码发送给客户。

我的HTTP状态代码为202(“已接受”),而不是401(“未经授权”)。

以下代码有什么问题吗?

[ServiceContract]
public interface Irestservice
{
    [OperationContract]
    [WebGet]
    bool signin(string username, string password);       
}


[ServiceBehavior(IncludeExceptionDetailInFaults = true,
                 InstanceContextMode = InstanceContextMode.PerCall),
                 AspNetCompatibilityRequirements(RequirementsMode =
                       AspNetCompatibilityRequirementsMode.Allowed)]
public class restservice : Irestservice
{

    [Authorization]
    public bool signin(string username, string password)
    {           
        return true;           
    }
}

public class AuthorizationAttribute : Attribute, IOperationBehavior,
                                                 IParameterInspector
{

    public void ApplyDispatchBehavior(
        OperationDescription operationDescription,
        DispatchOperation dispatchOperation)
    {           
        dispatchOperation.ParameterInspectors.Add(this);
    }       

    public void AfterCall(string operationName, object[] outputs,
                          object returnValue, object correlationState)
    {
    }

    public object BeforeCall(string operationName, object[] inputs)
    {
        string publicKey = WebOperationContext.Current
                               .IncomingRequest.Headers["Authorization"];
        bool flag = AuthorizationHelper.CheckPartnerAuthorization( publicKey);
        if (!flag)
        {
            WebOperationContext.Current.OutgoingResponse.StatusCode =
                HttpStatusCode.Unauthorized;
            throw new LicensingException("PartnerUnauthorized");
        }

        return null;
    }             
}

public class LicensingBehavior : IServiceBehavior
{           

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
                                      ServiceHostBase serviceHostBase)
    {
        foreach (ChannelDispatcher channelDispatcher in 
                 serviceHostBase.ChannelDispatchers)
        {               
            RestErrorHandler newHandler = new RestErrorHandler();
            channelDispatcher.ErrorHandlers.Add(newHandler);               
        }
    }
}

class AppServiceHostFactory : WebScriptServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType,
                                                     Uri[] baseAddresses)
    {   
        ServiceHost serviceHost =
            base.CreateServiceHost(serviceType, baseAddresses);
        serviceHost.Description.Behaviors.Add(new LicensingBehavior());
        return serviceHost;
    }     
}

public class RestErrorHandler:IErrorHandler
{
    #region IErrorHandler Members

    public bool HandleError(Exception error)
    {
        return error is LicensingException;
    }

    public void ProvideFault(Exception error, MessageVersion version,
                             ref Message fault)
    {
        LicensingException licensingException = error as LicensingException;
        if (licensingException != null)
        {

            fault = Message.CreateMessage(version, null,
                new ValidationErrorBodyWriter(licensingException));
            HttpResponseMessageProperty prop =
                new HttpResponseMessageProperty();
            prop.StatusCode = HttpStatusCode.Unauthorized;
            prop.Headers[HttpResponseHeader.ContentType] =
                "application/json; charset=utf-8";
            fault.Properties.Add(HttpResponseMessageProperty.Name, prop);
            fault.Properties.Add(WebBodyFormatMessageProperty.Name,
                new WebBodyFormatMessageProperty(WebContentFormat.Json));
        }            
    }

    class ValidationErrorBodyWriter : BodyWriter
    {
        private LicensingException licensingException;
        Encoding utf8Encoding = new UTF8Encoding(false);

        public ValidationErrorBodyWriter(LicensingException exception)
            : base(true)
        {
            this.licensingException = exception;
        }

        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
        {
            writer.WriteStartElement("root");
            writer.WriteAttributeString("type", "object");

            writer.WriteStartElement("ErrorMessage");
            writer.WriteAttributeString("type", "string");
            writer.WriteString(this.licensingException.Message);
            writer.WriteEndElement();

            writer.WriteEndElement();
        }
    }
}

3 个答案:

答案 0 :(得分:0)

您确定IErrorHandler接收的错误实际上是许可例外吗?请查看此post on error handling for webHttpBinding以确保您已正确实施ProvideFault方法。

答案 1 :(得分:0)

我正在使用工厂和serice配置。因此,工厂的行为掩盖了服务行为。因此,工厂和服务配置不应该一起使用。

答案 2 :(得分:0)

尝试在RestErrorHandler.ProvideFault中执行此操作:

var response = WebOperationContext.Current.OutgoingResponse;
response.StatusCode = HttpStatusCode.Unauthorized;