通过Azure Service Bus验证的WCF数据服务

时间:2012-11-11 12:35:25

标签: azure wcf-data-services azureservicebus

我坚持这个。我有一个WCF数据服务,可以在Azure Service Bus中成功创建HTTPS端点。

我最初使用<security relayClientAuthenticationType="None" />设置服务进行测试,并且我能够在客户端中正常使用该服务。

通过此服务的数据将是敏感的,因此要锁定它,我切换到服务的Web.Config文件中的<security relayClientAuthenticationType="RelayAccessToken" />

我使用以下代码获取我的令牌:

static string GetToken(string serviceNamespace, string issuerName, string issuerPassword)
    {
        if (_token == null)
        {
            string acsEndpoint = "https://" + serviceNamespace + "-sb.accesscontrol.windows.net/WRAPv0.9";
            string relyingPartyAddress = "http://" + serviceNamespace + ".servicebus.windows.net";

            NameValueCollection postData = new NameValueCollection
            {
                { "wrap_scope", relyingPartyAddress },
                { "wrap_name", issuerName },
                { "wrap_password", issuerPassword },
            };

            WebClient webClient = new WebClient();
            byte[] responseBuffer = webClient.UploadValues(acsEndpoint, "POST", postData);
            string response = Encoding.UTF8.GetString(responseBuffer);
            response = Uri.UnescapeDataString(response);

            string[] tokenVariables = response.Split('&');

            int tokenIndex = Array.FindIndex(tokenVariables, s => s.StartsWith("HMACSHA256"));

            string[] tokenVariable = tokenVariables[tokenIndex].Split('=');

            _token = HttpUtility.UrlDecode(tokenVariable[1]);
        }

        return _token;
    }
static string _token = null;

然后我使用context.SendingRequest += new EventHandler<SendingRequestEventArgs>(OnSendingRequest);和以下内容将我的令牌添加到我的REST请求的标头中:

static void OnSendingRequest(object sender, SendingRequestEventArgs e)
    {
        e.RequestHeaders.Add(
            "Authorization",
            string.Format("WRAP access_token=\"{0}\"", GetToken("MyNamespace", "owner", "MySecret") )
            );
    }

然后我的请求采用以下形式(在添加安全性之前完美运行)

try
        {
            var results = (from b in context.Banks where b.Bank1 != "Bank1" select b).Take(200).ToList();
            ViewBag.Results = results;
        }
        catch (DataServiceQueryException ex)
        {
            ViewBag.Message = "Authentication failed. A new token will be requested.";
            var code = ex.Response.StatusCode;
            if (code == 401)
                _token = null;
        }

当我开发代码来获取和附加令牌时,我遇到了大量令牌错误,所以我相信我现在成功获得了一个令牌,但现在我收到以下错误:

500 TrackingId:38940805-f9b3-4444-a8e3-2a00b2309cf6_G0,时间戳:11/11/2012 11:48:33 AM 描述:执行当前Web请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。 异常详细信息:System.Data.Services.Client.DataServiceClientException:500 TrackingId:38940805-f9b3-4444-a8e3-2a00b2309cf6_G0,时间戳:11/11/2012 11:48:33 AM 来源错误: 第31行:context.SendingRequest + = new EventHandler(OnSendingRequest); 第32行: 第33行:var results =(from b in context.Banks,其中b.Bank1!=&#34; Bank1&#34; select b).Take(200).ToList(); 第34行: 第35行:试试 源文件:c:\ Users \ v-tadam.REDMOND \ Documents \ Visual Studio 2012 \ Projects \ CFARPOC \ CFARPOCClient \ Controllers \ HomeController.cs Line:33 堆栈跟踪: [DataServiceClientException:500 TrackingId:38940805-f9b3-4444-a8e3-2a00b2309cf6_G0,Timestamp:11/11/2012 11:48:33 AM]    System.Data.Services.Client.QueryResult.Execute()+ 4146018    System.Data.Services.Client.DataServiceRequest.Execute(DataServiceContext context,QueryComponents queryComponents)+131 [DataServiceQueryException:处理此请求时发生错误。]    System.Data.Services.Client.DataServiceRequest.Execute(DataServiceContext context,QueryComponents queryComponents)+432    System.Data.Services.Client.DataServiceQuery`1.Execute()+77    System.Data.Services.Client.DataServiceQuery`1.GetEnumerator()+13    System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)+369    System.Linq.Enumerable.ToList(IEnumerable`1 source)+58    CFARPOCClient.Controllers.HomeController.Banks()在c:\ Users \ v-tadam.REDMOND \ Documents \ Visual Studio 2012 \ Projects \ CFARPOC \ CFARPOCClient \ Controllers \ HomeController.cs:33    lambda_method(Closure,ControllerBase,Object [])+101    System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller,Object []参数)+14    System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext,IDictionary`2参数)+211    System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext,ActionDescriptor actionDescriptor,IDictionary`2参数)+27    System.Web.Mvc.Async.c__DisplayClass42.b__41()+28    System.Web.Mvc.Async.c__DisplayClass8`1.b__7(IAsyncResult _)+10    System.Web.Mvc.Async.WrappedAsyncResult`1.End()+57    System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)+48    System.Web.Mvc.Async.c__DisplayClass39.b__33()+57    System.Web.Mvc.Async.c__DisplayClass4f.b__49()+223    System.Web.Mvc.Async.c__DisplayClass37.b__36(IAsyncResult asyncResult)+10    System.Web.Mvc.Async.WrappedAsyncResult`1.End()+57    System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult)+48    System.Web.Mvc.Async.c__DisplayClass2a.b__20()+24    System.Web.Mvc.Async.c__DisplayClass25.b__22(IAsyncResult asyncResult)+102    System.Web.Mvc.Async.WrappedAsyncResult`1.End()+57    System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult)+43    System.Web.Mvc.c__DisplayClass1d.b__18(IAsyncResult asyncResult)+14    System.Web.Mvc.Async.c__DisplayClass4.b__3(IAsyncResult ar)+23    System.Web.Mvc.Async.WrappedAsyncResult`1.End()+62    System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult)+57    System.Web.Mvc.Async.c__DisplayClass4.b__3(IAsyncResult ar)+23    System.Web.Mvc.Async.WrappedAsyncResult`1.End()+62    System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult)+47    System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult)+10    System.Web.Mvc.c__DisplayClass8.b__3(IAsyncResult asyncResult)+25    System.Web.Mvc.Async.c__DisplayClass4.b__3(IAsyncResult ar)+23    System.Web.Mvc.Async.WrappedAsyncResult`1.End()+62    System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)+47    System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)+9    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()+9629708    System.Web.HttpApplication.ExecuteStep(IExecutionStep step,Boolean&amp; completedSynchronously)+155

此错误无法帮助我找到问题。我究竟做错了什么?在安全性实施之前,我们已经完美地使用了这项服务,并且我已经完成了所有关于如何获取令牌并将其附加到我的请求的研究。我做错了有什么事吗?

1 个答案:

答案 0 :(得分:4)

我发现了自己的错误。我对构成令牌的内容有一个根本的误解。出于某种原因,我在脑海中得知它是“HMACSHA256”之后的文本,实际上令牌是“wrap_access_token =”之后响应中的所有内容(现在看来很明显......)

无论如何,如果有其他人遇到此问题,则会抛出500错误代码,因为正确检索了令牌,但错误的令牌正被添加到请求标头中。我通过附加“GARBAGETOKEN”并观察相同的行为来测试这个。

以下是有效的GetToken方法:

static string GetToken(string serviceNamespace, string issuerName, string issuerPassword)
    {
        if (_token == null)
        {
            string acsEndpoint = "https://" + serviceNamespace + "-sb.accesscontrol.windows.net/WRAPv0.9";
            string relyingPartyAddress = "http://" + serviceNamespace + ".servicebus.windows.net";

            NameValueCollection postData = new NameValueCollection
            {
                { "wrap_scope", relyingPartyAddress },
                { "wrap_name", issuerName },
                { "wrap_password", issuerPassword },
            };

            WebClient webClient = new WebClient();
            byte[] responseBuffer = webClient.UploadValues(acsEndpoint, "POST", postData);
            string response = Encoding.UTF8.GetString(responseBuffer);

            string token = response.Split('&')
                .Single(value => value.StartsWith("wrap_access_token=") )
                .Split('=')[1];

            _token = HttpUtility.UrlDecode(token);
        }

        return _token;
    }
    static string _token = null;

希望我的愚蠢帮助别人:)