本文介绍了WCF REST的某些方法基本身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在WCF 4.0中实现了不少的RESTful(GET和POST)方法。所有这些工作在SSL。

I have quite a few RESTful (GET and POST) methods implemented in WCF 4.0. All these work over SSL.

的一些方法的一个例子:

An example of some of the methods:

[OperationContract]
[WebInvoke(UriTemplate = "Login?", Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
LoginResponse Login(LoginRequest request);

[OperationContract]
[WebInvoke(UriTemplate = "UpdateDetails?", Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
UpdateUserDetailResponse UpdateDetails(UpdateUserDetailRequest request);

[OperationContract]
[WebInvoke(UriTemplate = "GetDetails?", Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
UserDetailResponse GetDetails(UserDetailRequest request);



我经历了这么多的博客和论坛看了看,我仍然无法找到的东西,满足
我的要求。我需要在的部分的方法而不是全部实施基本身份验证。如果你看一下上面的例子我需要用户名和密码,通过对UpdateDetails和GetDetails方法发送,而不是登录方法。然后用户名和密码进行身份验证针对数据库。是否有可能做这样的事情?

I have looked through so many blogs and forums and I still cannot find something that meetsmy requirements. I need to implement basic authentication on some of the methods but not all. If you look at the examples above I require a username and password to be sent through for the UpdateDetails and GetDetails method, but not for the Login method. The username and password is then authenticated against a database. Is it possible to do something like this?

作为一个方面说明:这些REST方法是由许多不同的移动设备名为

As a side note: these REST methods are called by many different mobile devices.

我已经看过。下面的网站,他们都实现了REST的基本身份验证,但的它们覆盖上述所有的方法。

I have looked at the following sites and they all implement basic authentication over REST but they cover all the methods mentioned above.




  • 的(底部链接不工作
    了)

  • http://msdn.microsoft.com/en-us/library/aa702565.aspx
  • Adding basic HTTP auth to a WCF REST service
  • http://custombasicauth.codeplex.com/ (links at the bottom don't workanymore)

是否有可能做我想做的事?

Is it possible to do what I want to do?

推荐答案

我创建了一个您在方法属性BasicAuthenticationInvoker类,你想验证如下:

I created a BasicAuthenticationInvoker class which you attribute on the methods you would like to authenticate as follows:

  [OperationContract]
    [BasicAuthenticationInvoker] // this is the auth attribute!
    [WebInvoke(UriTemplate = "QuickQuote?", Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
    QuickQuoteResponse QuickQuote(QuickQuoteRequest request);



实际的类看起来如下:

The actual class looks as follows:

 public class BasicAuthenticationInvoker : Attribute, IOperationBehavior, IOperationInvoker
    {
        #region Private Fields

        private IOperationInvoker _invoker;

        #endregion

        #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

        #region IOperationInvoker Members

        public object Invoke(object instance, object[] inputs, out object[] outputs)
        {
            if (Authenticate("Client Name here"))
                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

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

            if (credentials != null && credentials.Length == 2)
            {
                // do auth here
                var username = credentials[0];
                var password = credentials[1];

               // validate the username and password against whatever auth logic you have

                return true; // if successful
            }

            WebOperationContext.Current.OutgoingResponse.Headers["WWW-Authenticate"] = string.Format("Basic realm=\"{0}\"", realm);
            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
                {
                }
            }

            return null;
        }
    }

这篇关于WCF REST的某些方法基本身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 08:36