使用WCF REST服務進行基本身份驗證的內置方法?

[英]Built-in way to do Basic Authentication with WCF REST service?


I am using Basic Authentication in my WCF service. And also using ASP Membership provider for authentication.

我在我的WCF服務中使用基本身份驗證。並且還使用ASP Membership provider進行身份驗證。

Web.Config: For REST service:

Web.Config:對於REST服務:

<webHttpBinding>
    <binding name="webHttpBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="200065536" maxBufferPoolSize="200065536" maxReceivedMessageSize="200065536"   transferMode="Buffered" useDefaultWebProxy="true">
      <readerQuotas maxDepth="202048000" maxStringContentLength="202048000" maxArrayLength="202048000"
                    maxBytesPerRead="202048000" maxNameTableCharCount="202048000"/>
      <security mode="Transport">  
      </security>
    </binding>
  </webHttpBinding>

Authentication type and Mode:

驗證類型和模式:

<serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="CustomMemberShipProvider" />
</serviceCredentials>

My Custom class for BasicAuthentication before invoking any method. The code is shown below:

在調用任何方法之前,我的BasicAuthentication類。代碼如下所示:

namespace BasicAuth.Service
{
    public class BasicAuthenticationInvoker : Attribute, IOperationBehavior, IOperationInvoker
    {
        #region Private Fields

        private IOperationInvoker _invoker;

        #endregion Private Fields

        #region IOperationBehavior Members

        public void ApplyDispatchBehavior(OperationDescription operationDescription,
                                          DispatchOperation dispatchOperation)
        {
            _invoker = dispatchOperation.Invoker;
            dispatchOperation.Invoker = this;
        }

        public void ApplyClientBehavior(OperationDescription operationDescription,
                                        ClientOperation clientOperation)
        {
        }

        public void AddBindingParameters(OperationDescription operationDescription,
                                         BindingParameterCollection bindingParameters)
        {
        }

        public void Validate(OperationDescription operationDescription)
        {
        }

        #endregion IOperationBehavior Members

        #region IOperationInvoker Members

        public object Invoke(object instance, object[] inputs, out object[] outputs)
        {
            System.Diagnostics.Debugger.Break();
            if (Authenticate())
                return _invoker.Invoke(instance, inputs, out outputs);
            else
            {
                outputs = null;
                return null;
            }
        }

        public object[] AllocateInputs()
        {
            return _invoker.AllocateInputs();
        }

        public IAsyncResult InvokeBegin(object instance, object[] inputs,
                                        AsyncCallback callback, object state)
        {
            throw new NotSupportedException();
        }

        public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
        {
            throw new NotSupportedException();
        }

        public bool IsSynchronous
        {
            get
            {
                return true;
            }
        }

        #endregion IOperationInvoker Members

        private bool Authenticate()
        {
            string[] credentials = GetCredentials(WebOperationContext.Current.IncomingRequest.Headers);

            if (credentials != null && credentials.Length == 2)
            {
                var username = credentials[0];
                var password = credentials[1];
                if (Membership.ValidateUser(username, password))  //if valid user
                {
                    //get the roles of the user
                    string[] roles = Roles.GetRolesForUser(username);
                    Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(username), roles);
                    return true;
                }
            }
            WebOperationContext.Current.OutgoingResponse.Headers["WWW-Authenticate"] = string.Format("Basic realm=\"{0}\"", string.Empty);
            WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.Unauthorized;
            return false;
        }

        private string[] GetCredentials(WebHeaderCollection headers)
        {
            string credentials = WebOperationContext.Current.IncomingRequest.Headers["Authorization"];
            if (credentials != null)
                credentials = credentials.Trim();

            if (!string.IsNullOrEmpty(credentials))
            {
                try
                {
                    string[] credentialParts = credentials.Split(new[] { ' ' });
                    if (credentialParts.Length == 2 && credentialParts[0].Equals("basic", StringComparison.OrdinalIgnoreCase))
                    {
                        credentials = Encoding.ASCII.GetString(Convert.FromBase64String(credentialParts[1]));
                        credentialParts = credentials.Split(new[] { ':' });
                        if (credentialParts.Length == 2)
                            return credentialParts;
                    }
                }
                catch (Exception ex)
                {

                }
            }

            return null;
        }
    }
}

My Iservice looks like below:

我的Iservice如下所示:

My Custom class is used as an attribute in Iservice contract

我的Custom類用作Iservice合同中的屬性

public interface IService1
    {
        [OperationContract]
        [BasicAuthenticationInvoker] //my custom class for authentication
        [WebGet(UriTemplate = "GetString?userID={userID}",
            ResponseFormat = WebMessageFormat.Json)]
        string GetString(string userID);
   }

When calling the WCF REST service using the AJAX call, I add the Authentication header to the Request and authenticate the user using the above custom class.

使用AJAX調用調用WCF REST服務時,我將Authentication頭添加到請求中,並使用上面的自定義類對用戶進行身份驗證。

AJAX Call: Below is the Ajax call used to call service and used beforeSend to authenticte the user before accessing the service.

AJAX調用:下面是用於調用服務的Ajax調用,並使用beforeSend在訪問服務之前對用戶進行身份驗證。

<script>
             $(function () {
                 alert("onload");
                 $.ajax
                     ({
                         type: "GET",
                         data:jsondata,
                         url: https://localhost:446/BasicAuthService.svc/rest/GetString',
                         cache: false,
                         async: true,
                         crossDomain:true,
                         dataType: "json",
                         contentType: "application/json; charset=utf-8",
                         beforeSend: function (xhr) {                             
                             xhr.setRequestHeader('Authorization', 'Basic plc2gxMjMk');
                         },
                         error: function(jqXHR, exception)
                         {
                             alert(jqXHR.status+" "+exception);
                         }
                     });
             });
  </script>

My Question is:

我的問題是:

I hope you get the overall picture about how my code works.

我希望你能全面了解我的代碼是如何工作的。

So what I need is, Instead of using custom class for BasicAuthentication, how can I authenticate each request to the service ? Is there any In-build functionality in WCF for authenticating the incoming request ?

所以我需要的是,我如何驗證對服務的每個請求,而不是使用BasicAuthentication的自定義類? WCF中是否有用於驗證傳入請求的In-build功能?

Thanks in advance.

提前致謝。

1 个解决方案

#1


0  

Your security mode should specify basic authentication:

您的安全模式應指定基本身份驗證:

<security mode="Transport">
    <transport clientCredentialType="Basic" />
</security>

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2013/12/03/724ed3fdb1a3de677c3583b09ce5a3b7.html



 
粤ICP备14056181号  © 2014-2020 ITdaan.com