azure - 通过 Azure 服务总线进行身份验证的 WCF 数据服务

标签 azure wcf-data-services azureservicebus

我被困在这个问题上了。我有一个 WCF 数据服务,它在 Azure 服务总线中成功创建了 HTTPS 终结点。

我最初使用 <security relayClientAuthenticationType="None" /> 设置服务进行测试我能够在客户端中很好地使用该服务。

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

我使用以下代码来获取我的 token :

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);以及以下将我的 token 添加到我的 REST 请求的 header :

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;
        }

当我开发代码来获取并附加 token 时,我遇到了很多 token 错误,所以我相信我现在成功获取了 token ,但现在我收到以下错误:

500TrackingId:38940805-f9b3-4444-a8e3-2a00b2309cf6_G0, Timestamp:11/11/2012 11:48:33 AM Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.Data.Services.Client.DataServiceClientException: 500TrackingId:38940805-f9b3-4444-a8e3-2a00b2309cf6_G0, Timestamp:11/11/2012 11:48:33 AM Source Error: Line 31: context.SendingRequest += new EventHandler(OnSendingRequest); Line 32: Line 33: var results = (from b in context.Banks where b.Bank1 != "Bank1" select b).Take(200).ToList(); Line 34: Line 35: try Source File: c:\Users\v-tadam.REDMOND\Documents\Visual Studio 2012\Projects\CFARPOC\CFARPOCClient\Controllers\HomeController.cs Line: 33 Stack Trace: [DataServiceClientException: 500TrackingId:38940805-f9b3-4444-a8e3-2a00b2309cf6_G0, Timestamp:11/11/2012 11:48:33 AM] System.Data.Services.Client.QueryResult.Execute() +414618 System.Data.Services.Client.DataServiceRequest.Execute(DataServiceContext context, QueryComponents queryComponents) +131 [DataServiceQueryException: An error occurred while processing this request.] 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() in 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[] parameters) +14 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +211 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +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& completedSynchronously) +155

这个错误并不能帮助我找到问题所在。我究竟做错了什么?在实现安全性之前,使用该服务可以完美地工作,并且我已经完成了所有关于如何获取 token 并将其附加到我的请求的研究。有什么地方我做错了吗?

最佳答案

我发现了我的错误。我对代币的构成有一个根本性的误解。出于某种原因,我脑子里认为它是“HMACSHA256”后面的文本,而实际上 token 是“wrap_access_token =”后面的响应中的所有内容(现在看起来很明显......)

无论如何,如果其他人遇到此问题,则会抛出 500 错误代码,因为 token 已正确检索,但错误的 token 被添加到请求 header 中。我通过附加“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;

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

关于azure - 通过 Azure 服务总线进行身份验证的 WCF 数据服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13331172/

相关文章:

sql - 无法使用 monotouch 连接到 sql azure 数据库

security - 安全访问 SQL Azure

c# - 在 IIS 上尝试我的 WCF 数据服务时得到 "401 - Unauthorized"

azure - 与 Azure 服务总线一起使用时获取 MassTransit.RequestTimeoutException

azure - 服务总线中的传出消息是什么?

c# - 当 Service Bus Explorer 添加垃圾时如何读取消息正文 C# 重新提交消息时 http ://schemas. microsoft.com/2003/10/Serialization -

azure - 使用保留 IP 时无法更新 Azure 部署

azure - 如何更改 Azure SDK 2.5 中每个服务配置的诊断存储位置

wcf - 我应该使用 OData 还是开发自己的 WCF 服务?

.net - 何时使用 WCF 数据服务,何时不使用?