aspnet webforms 中的 WCF 服务抛出 302

WCF Service inside aspnet webforms throwing 302

我在现有的 ASPNET webforms 站点中创建了一个 WCF 服务,然后我继续将 FormsAuthentication 添加到 aspnet 站点,在位置标记中添加了一个部分以允许匿名访问 .svc 文件,我可以浏览WSDL 文件没有问题,但是当我尝试调用该服务时,我收到 302,该服务设置为使用 basicAuth。

我尝试添加一个 HttpModule 来拦截服务请求和 return 一个适当的消息,但它也不起作用。

这是服务文件夹中的 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 添加了一些其他事件,但 none 获得成功

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. 删除 .svc 文件的任何形式的安全措施
  2. 创建 messageInspector 以将基本身份验证 header 添加到 WCF(客户端)
  3. 将 messageInspector 添加到 ServiceBehavior
  4. 将 serviceBehavior 添加到您的服务端点行为
  5. 在服务中,创建一个ServiceAuthorizationManager
  6. 将 ServiceAuthorizationManager 添加到您服务的 web.config

1.Remove 任何证券

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

2.Create 一个 messageInspector,用于将 Basic Auth header 添加到 WCF(Client)

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.在Service中,创建一个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" />