Служба аутентификации WCF REST - PullRequest
1 голос
/ 11 июля 2011

Я создаю службу отдыха WCF с использованием WebScriptServiceHostFactory для поддержки форматов сообщений 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 голосов
/ 22 сентября 2011

Я использовал заводскую конфигурацию и серию. Таким образом, служебное поведение было переопределено поведением фабрики. Поэтому заводская и сервисная конфигурации не должны использоваться вместе.

0 голосов
/ 06 июля 2016

Попробуйте сделать это внутри RestErrorHandler.ProvideFault:

var response = WebOperationContext.Current.OutgoingResponse;
response.StatusCode = HttpStatusCode.Unauthorized;
0 голосов
/ 09 сентября 2011

Вы уверены, что ошибка, которую получает IErrorHandler, на самом деле является исключением из лицензии? Посмотрите на этот пост об обработке ошибок для webHttpBinding , чтобы убедиться, что вы правильно реализовали метод ProvideFault.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...