Служба WCF внутри веб-форм aspnet, выбрасывающих 302 - PullRequest
0 голосов
/ 08 октября 2018

Я создал службу WCF на существующем сайте веб-форм ASPNET, затем приступил к добавлению FormsAuthentication к сайту aspnet, добавил раздел в теге местоположения, чтобы разрешить анонимный доступ к файлу .svc, я могу просматривать WSDLфайл не проблема, но когда я пытаюсь вызвать службу, я получаю 302, служба настроена на использование basicAuth.

Я попытался добавить HttpModule для перехвата запроса службы и вернуть соответствующее сообщение, но это не такработать также.

Вот Webconfig внутри папки службы.

<?xml version="1.0"?>
<configuration>
  <system.web>
    <httpModules>
      <add name="AuthRedirectHandler" type="Test.Modules.AuthRedirectHandler, Test" />
    </httpModules>
    <authorization>
      <allow users="?"/>
    </authorization>
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="AuthRedirectHandler" type="Test.Modules.AuthRedirectHandler, Test" preCondition="managedHandler"/>
    </modules>
  </system.webServer>
</configuration>

HttpModule, добавил несколько других событий, но ни одно не получает

public class AuthRedirectHandler : IHttpModule
    {
        public void Dispose()
        {
            //throw new NotImplementedException(); -- do nothing here
        }

        public void Init(HttpApplication context)
        {
            context.EndRequest += new EventHandler(context_EndRequest);
            context.BeginRequest += Context_BeginRequest;
            context.AuthenticateRequest += Context_AuthenticateRequest;
            context.AuthorizeRequest += Context_AuthorizeRequest;
            context.PreRequestHandlerExecute += Context_PreRequestHandlerExecute;
            context.PostAuthorizeRequest += Context_PostAuthorizeRequest;
        }

        private void Context_PostAuthorizeRequest(object sender, EventArgs e)
        {
            int k = 0;
        }

        private void Context_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            int k = 0;
        }

        private void Context_AuthorizeRequest(object sender, EventArgs e)
        {
            int k = 0;
        }

        private void Context_AuthenticateRequest(object sender, EventArgs e)
        {
            int k = 0;
        }

        private void Context_BeginRequest(object sender, EventArgs e)
        {
            int k = 0;
        }

        void context_EndRequest(object sender, EventArgs e)
        {
            HttpApplication app = (HttpApplication) sender;

            if (app != null &&
                app.Response.StatusCode == 302)//302 Found
            {
                app.Response.ClearHeaders();
                app.Response.ClearContent();
                app.Response.StatusCode = 401;
            }
        }

КогдаЯ проверяю по запросу fiddler, я могу сделать нормальный запрос HttpWebRequest к службе, но когда я пытаюсь вызвать метод, я получаю ответ 302, который переходит к загрузке моей страницы входа.

1 Ответ

0 голосов
/ 20 ноября 2018

Это для некоторых, кому может понадобиться справка о том, как решить проблему, в итоге я пошел по этому маршруту

  1. Удалите все формы безопасности для файла .svc
  2. Создайте messageInspector для добавления заголовка Basic Auth к WCF (клиенту)
  3. Добавьте messageInspector к ServiceBehavior
  4. Добавьте serviceBehavior к поведению конечной точки службы
  5. В службе создайтеa ServiceAuthorizationManager
  6. Добавьте ServiceAuthorizationManager в web.config вашего сервиса

1. Снимите любую защиту

<location path="Services/UpdaterService.svc">
    <system.web>
      <authorization>
        <allow users="?"/>
      </authorization>
    </system.web>
  </location>

2.Создайте messageInspector для добавления заголовка Basic Auth в WCF (клиент)

public class ServiceMessageServiceCredentialsInspector : IClientMessageInspector
    {
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
        }

        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {

            HttpRequestMessageProperty requestMessageProperty = request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
            requestMessageProperty.Headers[HttpRequestHeader.Authorization] = "Basic " +
                    Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}"));

            return null;
        }
    }

3.Добавьте MessageInspector к ServiceBehavior

public class ServiceInterceptionBehavior : BehaviorExtensionElement,IEndpointBehavior
    {
        public override System.Type BehaviorType
        {
            get { return typeof(ServiceInterceptionBehavior); }
        }

        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {

        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(new ServiceMessageServiceCredentialsInspector());
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {

        }

        public void Validate(ServiceEndpoint endpoint)
        {
        }

        protected override object CreateBehavior()
        {
            throw new NotImplementedException();
        }
    }

4.Добавьте serviceBehavior к поведению вашей конечной точки сервиса

EndpointAddress address = new 
      EndpointAddress("http://localhost:14138/Services/Service.svc");
                        ChannelFactory<IService> myChannelFactory = new 
      ChannelFactory<IUpdaterService>(defaultBinding, address);
                            myChannelFactory.Endpoint.EndpointBehaviors.Add(new ServiceInterceptionBehavior());
                            var address2 = myChannelFactory.CreateChannel(address);

5.В Сервисе создайте ServiceAuthorizationManager

public class ServiceAuthorizationManager : ServiceAuthorizationManager
    {
        protected override bool CheckAccessCore(OperationContext operationContext)
        {
            //Extract the Athorizationm Header,a nd parse out the credentials converting to base64 string
            var authHeader = WebOperationContext.Current.IncomingRequest.Headers["Authorization"];
            if ((authHeader != null) && (authHeader != string.Empty))
            {
                var svcCredentials = System.Text.ASCIIEncoding.ASCII
                   .GetString(Convert.FromBase64String(authHeader.Substring(6)))
                   .Split(':');
                return DefaultPasswordValidator.ValidateCridentials(svcCredentials[0], svcCredentials[1]);
            }
            else
            {
                //No authorization header was provided, so challenge the client to provide before proceeding:
                WebOperationContext.Current.OutgoingResponse.Headers.Add("WWW-Authenticate: Basic realm=\"UpdaterService\"");
                //Throw an exception with the associated HTTP status code equivalent to HTTP status 401
                throw new FaultException("Please provide a username and password");
            }
        }

6.Добавьте ServiceAuthorizationManager в web.config вашего сервиса

<serviceAuthorization serviceAuthorizationManagerType="ServiceAuthorizationManager, AssemblyName, Version=2.0.0.1, Culture=neutral, PublicKeyToken=null" />
          <serviceAuthenticationManager serviceAuthenticationManagerType="ServiceAuthenticationManager, AssemblyName"
            authenticationSchemes="Basic" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...