开发者

Authentication WCF REST Service

I am building a WCF rest service using WebScriptServiceHostFactory to support both POX and Json Message formats and implemented the custom attribute to handle the Authorization for the operations. I would like to send the Status code as response and end the request for unauthorized requests so i am throwing exception from custom attribute and handling in IErrorHandler. But i am not able send the status code to client.

I am getting the HTTP status code as 202 ("Accepted") instead of 401 ("Unauthorized").

Is there anything wrong in the below code?

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


[ServiceBehavior(IncludeExceptionDetailInFaults = true,
                 InstanceContextMode = InstanceContextMode.PerCall),
开发者_JAVA百科                 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();
        }
    }
}


Are you sure that the error the IErrorHandler is receiving is actually a Licensing exception? Look at this post on error handling for webHttpBinding to ensure you've implemented the ProvideFault method correctly.


I was using the factory and also the serice configuration. So the service behaviour was overidden by the behavior of the factory. So the factory and the service configuration should not be used together.


Try doing this inside RestErrorHandler.ProvideFault:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜